Example #1
0
def setupROMSfiles(loc,date,ff,tout, time_units, tstride=1):
    '''
    setupROMSfiles()
    Kristen Thyng, March 2013

    Figures out necessary files to read in for track times and what
    model output indices within those files to use.

    Input:
     loc        File location. loc can be:
                * a thredds server web address
                * a single string of a file location
                * a list of strings of multiple file locations to be searched
                through
     date       datetime format start date
     ff         Time direction. ff=1 forward, ff=-1 backward
     tout       Number of model outputs to use
     time_units To convert to datetime
     tstride    Stride in time, in case want to use less model output
                 than is available. Default is 1, using all output.

    Output:
     nc         NetCDF object for relevant files
     tinds      Indices of outputs to use from fname files
    '''
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here: 
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')

    # For thredds server where all information is available in one place
    # or for a single file
    if 'http' in loc or type(loc)==str:
        nc = netCDF.Dataset(loc)

    # This is for the case when we have a bunch of files to sort through
    else:
        # the globbing should happen ahead of time so this case looks different than
        # the single file case
        nc = netCDF.MFDataset(loc) # files in fname are in chronological order

    # Convert date to number
    dates = netCDF.num2date(nc.variables['ocean_time'][:], time_units)
    # time index with time value just below date (relative to file ifile)
    istart = find(dates<=date)[-1]

    # Select indices 
    if ff==1:
        tinds = range(istart,istart+tout, tstride) # indices of model outputs desired
    else: # backward in time
        # have to shift istart since there are now new indices behind since going backward
        tinds = range(istart,istart-tout, -tstride)

    return nc, tinds
Example #2
0
File: inout.py Project: gijs/tracpy
def setupROMSfiles(loc,date,ff,tout, tstride=1):
    '''
    setupROMSfiles()
    Kristen Thyng, March 2013

    Figures out necessary files to read in for track times and what
    model output indices within those files to use.

    Input:
     loc        File location
     date       datetime format start date
     ff         Time direction. ff=1 forward, ff=-1 backward
     tout       Number of model outputs to use
     tstride    Stride in time, in case want to use less model output
                 than is available. Default is 1, using all output.

    Output:
     nc         NetCDF object for relevant files
     tinds      Indices of outputs to use from fname files
    '''
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here: 
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')

    # For thredds server where all information is available in one place
    if 'http' in loc:
        nc = netCDF.Dataset(loc)
        if ff == 1: #forward in time
            dates = nc.variables['ocean_time'][:] # don't stride here, need all times to make index determinations
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart,istart+tout, tstride) #use tstride here to get tinds correct
        else: #backward
            dates = nc.variables['ocean_time'][:]   
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart,istart-tout, -tstride) #use tstride here to get tinds correct

    # This is for the case when we have a bunch of files to sort through
    else:
        files = np.sort(glob.glob(loc)) # sorted list of file names

        # Find the list of files that cover the desired time period
        # First, check to see if there is one or more than one time index in each file because
        # if there is only one, we need to compare two files to see where we are in time
        # So, open the first file to check.
        nctemp = netCDF.Dataset(files[0])
        ttemp = nctemp.variables['ocean_time'][:]
        nctemp.close()
        if ttemp.size==1: # one output/time step per file. 
            noutputs = 1
            # Assume it is safe to open them all to search for starting place. Rest of indices
            # are checked below.
            nctemp = netCDF.MFDataset(files)
            ttemp = nctemp.variables['ocean_time'][:]
            nctemp.close()
            # find which time steps date is between and take earlier one as the starting file
            ifile = find(ttemp<=date)[0]

        else: # more than one output per file  
            noutputs = 0          
            for i,name in enumerate(files): # Loop through files
                nctemp = netCDF.Dataset(name)
                ttemp = nctemp.variables['ocean_time'][:]
                # pdb.set_trace()
                nctemp.close()
                # If datenum_in is larger than the first time in the file but smaller
                # than the last time, then this is the correct file to use to start
                if date >= ttemp[0] and date <= ttemp[-1]:
                    ifile = i # this is the starting file identifier then
                    break

        # Since the number of indices per file can change, make the process
        # of finding the necessary files a little more general
        # Start by opening two files
        i = 1
        fname = [files[ifile]]

        nc = netCDF.MFDataset(fname) # files in fname are in chronological order
        # Find which output in ifile is closest to the user-input start time (choose lower index)
        # Dates for drifters from this start date
        dates = nc.variables['ocean_time'][:]   
        ilow = date >= dates
        # time index with time value just below date (relative to file ifile)
        istart = dates[ilow].size - 1
        nc.close()
        # Select indices 
        if ff==1:
            tinds = range(istart,istart+tout, tstride) # indices of model outputs desired
        else: # backward in time
            # have to shift istart since there are now new indices behind since going backward
            tinds = range(istart,istart-tout, -tstride)
        # If we need more indices than available in these files, add another

        if ff==1:
            # If there is one output per file, just grab the number of necessary files
            if noutputs:
                fname = files[ifile:ifile+tout]
                nc = netCDF.MFDataset(fname) # files in fname are in chronological order

            else: # multiple snapshots per file

                # if the final index we want is beyond the length of these files,
                # keep adding files on
                while tinds[-1] > len(dates): 
                    # if tdir: #forward - add 2nd file on end
                    fname.append(files[ifile+i])
                    nc = netCDF.MFDataset(fname) # files in fname are in chronological order
                    dates = nc.variables['ocean_time'][:]   
                    ilow = date >= dates
                    # time index with time value just below datenum_in (relative to file ifile)
                    istart = dates[ilow].size - 1
                    tinds = range(istart,istart+tout, tstride)
                    nc.close()
                    i = i + 1

        else: #backwards in time
            while tinds[-1] < 0:
                fname.insert(0,files[ifile-i])
                nc = netCDF.MFDataset(fname)
                dates = nc.variables['ocean_time'][:]   
                ilow = date >= dates
                # time index with time value just below datenum_in (relative to file ifile)
                istart = dates[ilow].size - 1
                tinds = range(istart,istart-tout, -tstride)
                nc.close()
                i = i + 1

        # model output files together containing all necessary model outputs
        nc = netCDF.MFDataset(fname) # reopen since needed to close things in loop

    return nc, tinds
Example #3
0
File: inout.py Project: gijs/tracpy
def readgrid(grid_filename, vert_filename=None, llcrnrlon=-98.5, llcrnrlat=22.5, 
            urcrnrlon=-87.5, urcrnrlat=31.0, lat_0=30, lon_0=-94, res='i', 
            usebasemap=False, usespherical=True):
    '''
    readgrid(loc)
    Kristen Thyng, March 2013
    This function should be read in at the beginnind of a run.py call.
    It reads in all necessary grid information that won't change in time
    and stores it in a dictionary called grid.
    All arrays are changed to Fortran ordering (from Python ordering)
    and to tracmass variables ordering from ROMS ordering 
    i.e. from [t,k,j,i] to [i,j,k,t]
    right away after reading in.

    Input:
     grid_filename    File name (with extension) where grid information is stored
     vert_filename    (optional) File name (with extension) where vertical grid information
                    is stored, if not in grid_loc. Can also skip this if don't need 
                    vertical grid info.
     also optional basemap box parameters. Default is for full shelf model.
     usebasemap          (False) Whether to use load basemap into grid (True) or pyproj (False).
                    Basemap is slower but can be used for plotting, and pyproj is the opposite.

    Output:
     grid           Dictionary containing all necessary time-independent grid fields

    grid dictionary contains: (array sizing is for tracmass ordering)
     imt,jmt,km     Grid index sizing constants in (x,y,z), are for horizontal rho grid [scalar]
     dxv            Horizontal grid cell walls areas in x direction [imt,jmt-1]
     dyu            Horizontal grid cell walls areas in y direction [imt-1,jmt]
     dxdy           Horizontal area of cells defined at cell centers [imt,jmt]
     mask           Land/sea mask [imt,jmt] 
     pm,pn          Difference in horizontal grid spacing in x and y [imt,jmt]
     kmt            Number of vertical levels in horizontal space [imt,jmt]
     dzt0           Thickness in meters of grid at each k-level with time-independent free surface. 
                    Surface is at km [imt,jmt,km].
     zrt0           Depth in meters of grid at each k-level on vertical rho grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     zwt0           Depth in meters of grid at each k-level on vertical w grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     xr,yr          Rho grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xu,yu          U grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xv,yv          V grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xpsi,ypsi      Psi grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     X,Y            Grid index arrays
     tri,trir       Delaunay triangulations
     Cs_r,sc_r      Vertical grid streching paramters [km-1]
     hc             Critical depth [scalar]
     h              Depths [imt,jmt]
     theta_s        Vertical stretching parameter [scalar]. A parameter 
                    (typically 0.0 <= theta_s < 5.0) that defines the amount 
                    of grid focusing. A higher value for theta_s will focus the grid more.
     theta_b        Vertical stretching parameter [scalar]. A parameter (0.0 < theta_b < 1.0) 
                    that says whether the coordinate will be focused at the surface 
                    (theta_b -> 1.0) or split evenly between surface and bottom (theta_b -> 0)
     basemap        Basemap object

    Note: all are in fortran ordering and tracmass ordering except for X, Y, tri, and tric
    To test: [array].flags['F_CONTIGUOUS'] will return true if it is fortran ordering
    '''
    keeptime = 0 # do timing for readgrid
    if keeptime: starttime = time.time()

    # Read in grid parameters and find x and y in domain on different grids
    # use full dataset to get grid information
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here:
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')
    gridfile = netCDF.Dataset(grid_filename)

    # # Read in whether grid is spherical or not
    # try:
    #     usesphericaltemp = gridfile.variables['spherical'][:]
    #     if usesphericaltemp == 'T':
    #         usespherical = True
    #     else:
    #         usespherical = False
    # except KeyError: # Assume not lon/lat if spherical flag is not in grid file
    #     usespherical = False

    # Basemap parameters.
    if usespherical:
        llcrnrlon=llcrnrlon; llcrnrlat=llcrnrlat; 
        urcrnrlon=urcrnrlon; urcrnrlat=urcrnrlat; projection='lcc'
        lat_0=lat_0; lon_0=lon_0; resolution=res; area_thresh=0.
        # pdb.set_trace()
        if usebasemap:
            from mpl_toolkits.basemap import Basemap
            basemap = Basemap(llcrnrlon=llcrnrlon,
                         llcrnrlat=llcrnrlat,
                         urcrnrlon=urcrnrlon,
                         urcrnrlat=urcrnrlat,
                         projection=projection,
                         lat_0=lat_0,
                         lon_0=lon_0,
                         resolution=resolution,
                         area_thresh=area_thresh)
        else:
            from pyproj import Proj
            # this gives somewhat different differences between projected coordinates as compared with previous basemap
            # definition for the default values.
            basemap = Proj(proj='lcc', lat_1=llcrnrlat, lat_2=urcrnrlat, lat_0=lat_0, lon_0=lon_0, x_0=0, y_0=0,ellps='clrk66',datum='NAD27')
            # basemap = (proj='lcc',lat_1=44.33333333333334,lat_2=46,lat_0=43.66666666666666, lon_0=-120.5,x_0=609601.2192024384, y_0=0,ellps='clrk66',datum='NAD27')
            # basemap = Proj("+proj=lcc +lat_0=lat_0 +lon_0=lon_0")
                            # +x_0=1700000 \
                            # +y_0=300000 \
                            # +no_defs \
                            # +a=6378137 \
                            # +rf=298.257222101 \
                            # +to_meter=1")
        if keeptime: 
            basemaptime = time.time()
            print "basemap time ", basemaptime - starttime
    else:
        basemap = []

    if usespherical:
        lonu = gridfile.variables['lon_u'][:]
        latu = gridfile.variables['lat_u'][:]
        xu, yu = basemap(lonu,latu)
        lonv = gridfile.variables['lon_v'][:]
        latv = gridfile.variables['lat_v'][:]
        xv, yv = basemap(lonv,latv)
        lonr = gridfile.variables['lon_rho'][:]#[1:-1,1:-1]
        latr = gridfile.variables['lat_rho'][:]#[1:-1,1:-1]
        xr, yr = basemap(lonr,latr)
        lonpsi = gridfile.variables['lon_psi'][:]
        latpsi = gridfile.variables['lat_psi'][:]
        xpsi, ypsi = basemap(lonpsi,latpsi)
    else:
        # read cartesian data
        xu = gridfile.variables['x_u'][:]
        yu = gridfile.variables['y_u'][:]
        xv = gridfile.variables['x_v'][:]
        yv = gridfile.variables['y_v'][:]
        xr = gridfile.variables['x_rho'][:]
        yr = gridfile.variables['y_rho'][:]
        xpsi = gridfile.variables['x_psi'][:]
        ypsi = gridfile.variables['y_psi'][:]

        # assign to spherical arrays
        lonu, latu = xu, yu
        lonv, latv = xv, yv
        lonr, latr = xr, yr
        lonpsi, latpsi = xpsi, ypsi

    # Create mask of all active cells if there isn't one already
    try:
        mask = gridfile.variables['mask_rho'][:]#[1:-1,1:-1]
    except KeyError:
        mask = np.ones_like(xr)

    pm = gridfile.variables['pm'][:]
    pn = gridfile.variables['pn'][:]
    h = gridfile.variables['h'][:]
    if keeptime:
        hgridtime = time.time()
        print "horizontal grid time ", hgridtime - basemaptime

    # Vertical grid metrics
    if 's_w' in gridfile.variables: # then given grid file contains vertical grid info
        sc_r = gridfile.variables['s_w'][:] # sigma coords, 31 layers
        Cs_r = gridfile.variables['Cs_w'][:] # stretching curve in sigma coords, 31 layers
        hc = gridfile.variables['hc'][:]
        theta_s = gridfile.variables['theta_s'][:]
        theta_b = gridfile.variables['theta_b'][:]
        Vtransform = gridfile.variables['Vtransform'][0]
        Vstretching = gridfile.variables['Vstretching'][0]
    # Still want vertical grid metrics, but are in separate file
    elif vert_filename is not None:
        nc = netCDF.Dataset(vert_filename)
        sc_r = nc.variables['s_w'][:] # sigma coords, 31 layers
        Cs_r = nc.variables['Cs_w'][:] # stretching curve in sigma coords, 31 layers
        hc = nc.variables['hc'][:]
        theta_s = nc.variables['theta_s'][:]
        theta_b = nc.variables['theta_b'][:]
        Vtransform = nc.variables['Vtransform'][:]
        Vstretching = nc.variables['Vstretching'][:]

    if keeptime: 
        vgridtime = time.time()
        print "vertical grid time ", vgridtime - hgridtime

    # make arrays in same order as is expected in the fortran code
    # ROMS expects [time x k x j x i] but tracmass is expecting [i x j x k x time]
    # change these arrays to be fortran-directioned instead of python
    # This is faster than copying arrays. To test: .flags['F_CONTIGUOUS']
    mask = np.asfortranarray(mask.T)
    xr = np.asfortranarray(xr.T)
    yr = np.asfortranarray(yr.T)
    xu = np.asfortranarray(xu.T)
    yu = np.asfortranarray(yu.T)
    xv = np.asfortranarray(xv.T)
    yv = np.asfortranarray(yv.T)
    xpsi = np.asfortranarray(xpsi.T)
    ypsi = np.asfortranarray(ypsi.T)
    lonr = np.asfortranarray(lonr.T)

    latr = np.asfortranarray(latr.T)
    lonu = np.asfortranarray(lonu.T)
    latu = np.asfortranarray(latu.T)
    lonv = np.asfortranarray(lonv.T)
    latv = np.asfortranarray(latv.T)
    lonpsi = np.asfortranarray(lonpsi.T)
    latpsi = np.asfortranarray(latpsi.T)
    pm = np.asfortranarray(pm.T)
    pn = np.asfortranarray(pn.T)
    h = np.asfortranarray(h.T)

    if keeptime: 
        fortranflippingtime = time.time()
        print "fortran flipping time ", fortranflippingtime - vgridtime

    # Basing this on setupgrid.f95 for rutgersNWA example project from Bror
    # Grid sizes
    imt = h.shape[0] # 671
    jmt = h.shape[1] # 191
    if 'sc_r' in dir():
        km = sc_r.shape[0]-1 # 30 NOT SURE ON THIS ONE YET

    if keeptime: 
        gridsizetime = time.time()
        print "grid size time ", gridsizetime - fortranflippingtime

    # Index grid, for interpolation between real and grid space
    # this is for psi grid, so that middle of grid is min + .5 value
    # # X goes from 0 to imt-2 and Y goes from 0 to jmt-2
    # Y, X = np.meshgrid(np.arange(jmt-1),np.arange(imt-1)) # grid in index coordinates, without ghost cells
    # This is for rho
    # X goes from 0 to imt-1 and Y goes from 0 to jmt-1
    Y, X = np.meshgrid(np.arange(jmt),np.arange(imt)) # grid in index coordinates, without ghost cells
    # Triangulation for grid space to curvilinear space
    tri = delaunay.Triangulation(X.flatten(),Y.flatten())
    # Triangulation for curvilinear space to grid space
    # pdb.set_trace()
    trir = delaunay.Triangulation(xr.flatten(),yr.flatten())
    trirllrho = delaunay.Triangulation(lonr.flatten(),latr.flatten())

    if keeptime: 
        delaunaytime = time.time()
        print "delaunay time ", delaunaytime - gridsizetime

    # tracmass ordering.
    # Not sure how to convert this to pm, pn with appropriate shift
    dxv = 1/pm # pm is 1/\Delta x at cell centers
    dyu = 1/pn # pn is 1/\Delta y at cell centers

    dxdy = dyu*dxv

    # Change dxv,dyu to be correct u and v grid size after having 
    # them be too big for dxdy calculation. This is not in the 
    # rutgersNWA example and I am not sure why. [i,j]
    dxv = 0.5*(dxv[:,:-1]+dxv[:,1:])
    dyu = 0.5*(dyu[:-1,:]+dyu[1:,:])
    # # These should be interpolated
    # dxv = dxv[:,:-1]
    # dyu = dyu[:-1,:]

    if keeptime: 
        gridmetricstime = time.time()
        print "grid metrics time ", gridmetricstime - delaunaytime

    # Adjust masking according to setupgrid.f95 for rutgersNWA example project from Bror
    if 'sc_r' in dir():
        mask2 = mask.copy()
        kmt = np.ones((imt,jmt),order='f')*km
        ind = (mask2==1)
        ind[0:imt-1,:] = ind[1:imt,:]
        mask2[ind] = 1
        ind = (mask2==1)
        ind[:,0:jmt-1] = ind[:,1:jmt]
        mask2[ind] = 1
        # ind = (mask[1:imt-1,:]==1)
        # mask[0:imt-2,ind] = 1
        # ind = (mask[:,1:imt-1]==1)
        # mask[:,0:jmt-2] = 1
        ind = (mask2==0)
        kmt[ind] = 0

        # Use octant to calculate depths/thicknesses for the appropriate vertical grid parameters
        # have to transform a few back to ROMS coordinates and python ordering for this
        zwt0 = octant.depths.get_zw(Vtransform, Vstretching, km+1, theta_s, theta_b, 
                        h.T.copy(order='c'), 
                        hc, zeta=0, Hscale=3)
        zrt0 = octant.depths.get_zrho(Vtransform, Vstretching, km, theta_s, theta_b, 
                        h.T.copy(order='c'), 
                        hc, zeta=0, Hscale=3)
        # Change dzt to tracmass/fortran ordering
        zwt0 = zwt0.T.copy(order='f')
        zrt0 = zrt0.T.copy(order='f')
        # this should be the base grid layer thickness that doesn't change in time because it 
        # is for the reference vertical level
        dzt0 = zwt0[:,:,1:] - zwt0[:,:,:-1]

    if keeptime: 
        calculatingdepthstime = time.time()
        print "calculating depths time ", calculatingdepthstime - gridmetricstime

    # Fill in grid structure
    if 'sc_r' in dir():
        grid = {'imt':imt,'jmt':jmt,'km':km,#'angle':angle, 
            'dxv':dxv,'dyu':dyu,'dxdy':dxdy, 
            'mask':mask,'kmt':kmt,'dzt0':dzt0,
            'zrt0':zrt0,'zwt0':zwt0,
            'pm':pm,'pn':pn,'tri':tri,'trir':trir,'trirllrho':trirllrho,
            'xr':xr,'xu':xu,'xv':xv,'xpsi':xpsi,'X':X,
            'yr':yr,'yu':yu,'yv':yv,'ypsi':ypsi,'Y':Y,
            'lonr':lonr,'lonu':lonu,'lonv':lonv,'lonpsi':lonpsi,
            'latr':latr,'latu':latu,'latv':yv,'latpsi':latpsi,
            'Cs_r':Cs_r,'sc_r':sc_r,'hc':hc,'h':h, 
            'theta_s':theta_s,'theta_b':theta_b,
            'Vtransform':Vtransform, 'Vstretching':Vstretching,
            'basemap':basemap}
    else:
        grid = {'imt':imt,'jmt':jmt, #'angle':angle,
            'dxv':dxv,'dyu':dyu,'dxdy':dxdy, 
            'mask':mask,
            'pm':pm,'pn':pn,'tri':tri,'trir':trir,'trirllrho':trirllrho,
            'xr':xr,'xu':xu,'xv':xv,'xpsi':xpsi,'X':X,
            'yr':yr,'yu':yu,'yv':yv,'ypsi':ypsi,'Y':Y,
            'lonr':lonr,'lonu':lonu,'lonv':lonv,'lonpsi':lonpsi,
            'latr':latr,'latu':latu,'latv':yv,'latpsi':latpsi,
            'h':h, 
            'basemap':basemap}
 
    if keeptime: 
        griddicttime = time.time()
        print "saving grid dict time ", griddicttime - calculatingdepthstime

    gridfile.close()

    return grid
Example #4
0
def setupROMSfiles(loc,date,ff,tout):
    '''
    setupROMSfiles()
    Kristen Thyng, March 2013

    Figures out necessary files to read in for track times and what
    model output indices within those files to use.

    Input:
     loc    File location
     date   datetime format start date
     ff     Time direction. ff=1 forward, ff=-1 backward
     tout   Number of model outputs to use

    Output:
     nc     NetCDF object for relevant files
     tinds  Indices of outputs to use from fname files
    '''
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here: 
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')

    # pdb.set_trace()
    if 'http' in loc or len(loc) == 2: # use just input file
        if len(loc) == 2:
            nc = netCDF.Dataset(loc[0])
        else:
            nc = netCDF.Dataset(loc)
        if ff == 1: #forward in time
            dates = nc.variables['ocean_time'][:]   
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart,istart+tout)
        else: #backward
            dates = nc.variables['ocean_time'][:]   
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart,istart-tout,-1)

    # This is for the case when we have a bunch of files to sort through
    else:
        # pdb.set_trace()
        files = np.sort(glob.glob(loc + 'ocean_his_????.nc')) # sorted list of file names
        # files = np.sort(glob.glob(loc + 'ocean_his_*_tochange.nc')) # this is for idealized tests

        # Find the list of files that cover the desired time period
        for i,name in enumerate(files): # Loop through files
            nctemp = netCDF.Dataset(name)
            ttemp = nctemp.variables['ocean_time'][:]
            # pdb.set_trace()
            nctemp.close()
            # If datenum_in is larger than the first time in the file but smaller
            # than the last time, then this is the correct file to use to start
            if date > ttemp[0] and date <= ttemp[-1]:
                ifile = i # this is the starting file identifier then
                break

        # Since the number of indices per file can change, make the process
        # of finding the necessary files a little more general
        # Start by opening two files
        i = 1
        # pdb.set_trace()
        fname = [files[ifile]]

        nc = netCDF.MFDataset(fname) # files in fname are in chronological order
        # number of indices included in opened files so far
        ninds = nc.variables['ocean_time'][:].size 
        # Find which output in ifile is closest to the user-input start time (choose lower index)
        # Dates for drifters from this start date
        dates = nc.variables['ocean_time'][:]   
        ilow = date >= dates
        # time index with time value just below date (relative to file ifile)
        istart = dates[ilow].size - 1
        nc.close()
        # Select indices 
        if ff==1:
            tinds = range(istart,istart+tout) # indices of model outputs desired
        else: # backward in time
            # have to shift istart since there are now new indices behind since going backward
            tinds = range(istart,istart-tout,-1)
        # If we need more indices than available in these files, add another

        if ff==1:
            # if the final index we want is beyond the length of these files,
            # keep adding files on
            while tinds[-1] >= len(dates): 
                # if tdir: #forward - add 2nd file on end
                fname.append(files[ifile+i])
                nc = netCDF.MFDataset(fname) # files in fname are in chronological order
                dates = nc.variables['ocean_time'][:]   
                ilow = date >= dates
                # time index with time value just below datenum_in (relative to file ifile)
                istart = dates[ilow].size - 1
                tinds = range(istart,istart+tout)
                nc.close()
                i = i + 1
        else: #backwards in time
            while tinds[-1] < 0:
                fname.insert(0,files[ifile-i])
                nc = netCDF.MFDataset(fname)
                dates = nc.variables['ocean_time'][:]   
                ilow = date >= dates
                # time index with time value just below datenum_in (relative to file ifile)
                istart = dates[ilow].size - 1
                tinds = range(istart,istart-tout,-1)
                nc.close()
                i = i + 1

        # model output files together containing all necessary model outputs
        nc = netCDF.MFDataset(fname) # reopen since needed to close things in loop
    # pdb.set_trace()
    return nc, tinds
Example #5
0
def readgrid(loc, nc=None, llcrnrlon=-98.5, llcrnrlat=22.5, 
            urcrnrlon=-87.5, urcrnrlat=31.0):
    '''
    readgrid(loc)
    Kristen Thyng, March 2013
    This function should be read in at the beginnind of a run.py call.
    It reads in all necessary grid information that won't change in time
    and stores it in a dictionary called grid.
    All arrays are changed to Fortran ordering (from Python ordering)
    and to tracmass variables ordering from ROMS ordering 
    i.e. from [t,k,j,i] to [i,j,k,t]
    right away after reading in.

    Input:
     loc            File location
     nc             (optional) NetCDF object for relevant files
     also optional basemap box parameters. Default is for full shelf model.


    Output:
     grid           Dictionary containing all necessary time-independent grid fields

    grid dictionary contains: (array sizing is for tracmass ordering)
     imt,jmt,km     Grid index sizing constants in (x,y,z), are for horizontal rho grid [scalar]
     dxv            Horizontal grid cell walls areas in x direction [imt,jmt-1]
     dyu            Horizontal grid cell walls areas in y direction [imt-1,jmt]
     dxdy           Horizontal area of cells defined at cell centers [imt,jmt]
     mask           Land/sea mask [imt,jmt] 
     pm,pn          Difference in horizontal grid spacing in x and y [imt,jmt]
     kmt            Number of vertical levels in horizontal space [imt,jmt]
     dzt0           Thickness in meters of grid at each k-level with time-independent free surface. 
                    Surface is at km [imt,jmt,km].
     zrt0           Depth in meters of grid at each k-level on vertical rho grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     zwt0           Depth in meters of grid at each k-level on vertical w grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     xr,yr          Rho grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xu,yu          U grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xv,yv          V grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xpsi,ypsi      Psi grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     X,Y            Grid index arrays
     tri,trir       Delaunay triangulations
     Cs_r,sc_r      Vertical grid streching paramters [km-1]
     hc             Critical depth [scalar]
     h              Depths [imt,jmt]
     theta_s        Vertical stretching parameter [scalar]. A parameter 
                    (typically 0.0 <= theta_s < 5.0) that defines the amount 
                    of grid focusing. A higher value for theta_s will focus the grid more.
     theta_b        Vertical stretching parameter [scalar]. A parameter (0.0 < theta_b < 1.0) 
                    that says whether the coordinate will be focused at the surface 
                    (theta_b -> 1.0) or split evenly between surface and bottom (theta_b -> 0)
     basemap        Basemap object

    Note: all are in fortran ordering and tracmass ordering except for X, Y, tri, and tric
    To test: [array].flags['F_CONTIGUOUS'] will return true if it is fortran ordering
    '''

    # Basemap parameters.
    llcrnrlon=llcrnrlon; llcrnrlat=llcrnrlat; 
    urcrnrlon=urcrnrlon; urcrnrlat=urcrnrlat; projection='lcc'
    lat_0=30; lon_0=-94; resolution='i'; area_thresh=0.
    basemap = Basemap(llcrnrlon=llcrnrlon,
                 llcrnrlat=llcrnrlat,
                 urcrnrlon=urcrnrlon,
                 urcrnrlat=urcrnrlat,
                 projection=projection,
                 lat_0=lat_0,
                 lon_0=lon_0,
                 resolution=resolution,
                 area_thresh=area_thresh)

    # Read in grid parameters and find x and y in domain on different grids
    # if len(loc) == 2:
    #   gridfile = netCDF.Dataset(loc[1])
    # use full dataset to get grid information
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here: 
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')
    # pdb.set_trace()
    # grid is included in nc file if using thredds or forecast output
    if 'http' in loc:
        gridfile = netCDF.Dataset(loc)
    elif len(loc) == 2:
        gridfile = netCDF.Dataset(loc[1])
    else:
        gridfile = netCDF.Dataset(loc + 'grid.nc')
    lonu = gridfile.variables['lon_u'][:]
    latu = gridfile.variables['lat_u'][:]
    xu, yu = basemap(lonu,latu)
    lonv = gridfile.variables['lon_v'][:]
    latv = gridfile.variables['lat_v'][:]
    xv, yv = basemap(lonv,latv)
    lonr = gridfile.variables['lon_rho'][:]#[1:-1,1:-1]
    latr = gridfile.variables['lat_rho'][:]#[1:-1,1:-1]
    xr, yr = basemap(lonr,latr)
    lonpsi = gridfile.variables['lon_psi'][:]
    latpsi = gridfile.variables['lat_psi'][:]
    xpsi, ypsi = basemap(lonpsi,latpsi)
    mask = gridfile.variables['mask_rho'][:]#[1:-1,1:-1]
    pm = gridfile.variables['pm'][:]
    pn = gridfile.variables['pn'][:]
    h = gridfile.variables['h'][:]

    # Vertical grid metrics
    if 'http' in loc or len(loc) == 2:
        sc_r = gridfile.variables['s_w'][:] # sigma coords, 31 layers
        Cs_r = gridfile.variables['Cs_w'][:] # stretching curve in sigma coords, 31 layers
        hc = gridfile.variables['hc'][:]
        theta_s = gridfile.variables['theta_s'][:]
        theta_b = gridfile.variables['theta_b'][:]
    elif nc is not None: # for if running off local grid/nc files
        sc_r = nc.variables['s_w'][:] # sigma coords, 31 layers
        Cs_r = nc.variables['Cs_w'][:] # stretching curve in sigma coords, 31 layers
        hc = nc.variables['hc'][:]
        theta_s = nc.variables['theta_s'][:]
        theta_b = nc.variables['theta_b'][:]

    # make arrays in same order as is expected in the fortran code
    # ROMS expects [time x k x j x i] but tracmass is expecting [i x j x k x time]
    # change these arrays to be fortran-directioned instead of python
    # tic = time.time()
    # This is faster than copying arrays. To test: .flags['F_CONTIGUOUS']
    mask = np.asfortranarray(mask.T)
    xr = np.asfortranarray(xr.T)
    yr = np.asfortranarray(yr.T)
    xu = np.asfortranarray(xu.T)
    yu = np.asfortranarray(yu.T)
    xv = np.asfortranarray(xv.T)
    yv = np.asfortranarray(yv.T)
    xpsi = np.asfortranarray(xpsi.T)
    ypsi = np.asfortranarray(ypsi.T)
    lonr = np.asfortranarray(lonr.T)

    latr = np.asfortranarray(latr.T)
    lonu = np.asfortranarray(lonu.T)
    latu = np.asfortranarray(latu.T)
    lonv = np.asfortranarray(lonv.T)
    latv = np.asfortranarray(latv.T)
    lonpsi = np.asfortranarray(lonpsi.T)
    latpsi = np.asfortranarray(latpsi.T)
    pm = np.asfortranarray(pm.T)
    pn = np.asfortranarray(pn.T)
    h = np.asfortranarray(h.T)
    # print "fortran time ",time.time()-tic
    # pdb.set_trace()

    # Basing this on setupgrid.f95 for rutgersNWA example project from Bror
    # Grid sizes
    imt = h.shape[0] # 671
    jmt = h.shape[1] # 191
    # km = sc_r.shape[0] # 31
    if ('http' in loc) or (nc is not None) or len(loc) == 2:
        km = sc_r.shape[0]-1 # 30 NOT SURE ON THIS ONE YET

    # Index grid, for interpolation between real and grid space
    # this is for psi grid, so that middle of grid is min + .5 value
    # # X goes from 0 to imt-2 and Y goes from 0 to jmt-2
    # Y, X = np.meshgrid(np.arange(jmt-1),np.arange(imt-1)) # grid in index coordinates, without ghost cells
    # This is for rho
    # X goes from 0 to imt-1 and Y goes from 0 to jmt-1
    Y, X = np.meshgrid(np.arange(jmt),np.arange(imt)) # grid in index coordinates, without ghost cells
    # Triangulation for grid space to curvilinear space
    tri = delaunay.Triangulation(X.flatten(),Y.flatten())
    # Triangulation for curvilinear space to grid space
    trir = delaunay.Triangulation(xr.flatten(),yr.flatten())
    trirllrho = delaunay.Triangulation(lonr.flatten(),latr.flatten())

    # tracmass ordering.
    # Not sure how to convert this to pm, pn with appropriate shift
    dxv = 1/pm #.copy() # pm is 1/\Delta x at cell centers
    dyu = 1/pn #.copy() # pn is 1/\Delta y at cell centers

    # dxv = xr.copy()
    # dxv[0:imt-2,:] = dxv[1:imt-1,:] - dxv[0:imt-2,:]
    # dxv[imt-1:imt,:] = dxv[imt-3:imt-2,:]
    # # pdb.set_trace()
    # dyu = yr.copy()
    # dyu[:,0:jmt-2] = dyu[:,1:jmt-1] - dyu[:,0:jmt-2]
    # dyu[:,jmt-1] = dyu[:,jmt-2]
    dxdy = dyu*dxv

    # Change dxv,dyu to be correct u and v grid size after having 
    # them be too big for dxdy calculation. This is not in the 
    # rutgersNWA example and I am not sure why. [i,j]
    dxv = 0.5*(dxv[:,:-1]+dxv[:,1:])
    dyu = 0.5*(dyu[:-1,:]+dyu[1:,:])
    # # These should be interpolated
    # dxv = dxv[:,:-1]
    # dyu = dyu[:-1,:]

    # Adjust masking according to setupgrid.f95 for rutgersNWA example project from Bror
    # pdb.set_trace()
    if ('http' in loc) or (nc is not None) or len(loc) == 2:
        mask2 = mask.copy()
        kmt = np.ones((imt,jmt),order='f')*km
        ind = (mask2[1:imt,:]==1)
        mask2[0:imt-1,ind] = 1
        ind = (mask2[:,1:jmt]==1)
        mask2[ind,0:jmt-1] = 1
        # ind = (mask[1:imt-1,:]==1)
        # mask[0:imt-2,ind] = 1
        # ind = (mask[:,1:imt-1]==1)
        # mask[:,0:jmt-2] = 1
        ind = (mask2==0)
        kmt[ind] = 0

        # Use octant to calculate depths/thicknesses for the appropriate vertical grid parameters
        # have to transform a few back to ROMS coordinates and python ordering for this
        zwt0 = octant.depths.get_zw(1, 1, km+1, theta_s, theta_b, 
                        h.T.copy(order='c'), 
                        hc, zeta=0, Hscale=3)
        zrt0 = octant.depths.get_zrho(1, 1, km, theta_s, theta_b, 
                        h.T.copy(order='c'), 
                        hc, zeta=0, Hscale=3)
        # Change dzt to tracmass/fortran ordering
        zwt0 = zwt0.T.copy(order='f')
        zrt0 = zrt0.T.copy(order='f')
        # this should be the base grid layer thickness that doesn't change in time because it 
        # is for the reference vertical level
        dzt0 = zwt0[:,:,1:] - zwt0[:,:,:-1]

    # Fill in grid structure
    if ('http' in loc) or (nc is not None) or len(loc) == 2:
        grid = {'imt':imt,'jmt':jmt,'km':km, 
            'dxv':dxv,'dyu':dyu,'dxdy':dxdy, 
            'mask':mask,'kmt':kmt,'dzt0':dzt0,
            'zrt0':zrt0,'zwt0':zwt0,
            'pm':pm,'pn':pn,'tri':tri,'trir':trir,'trirllrho':trirllrho,
            'xr':xr,'xu':xu,'xv':xv,'xpsi':xpsi,'X':X,
            'yr':yr,'yu':yu,'yv':yv,'ypsi':ypsi,'Y':Y,
            'lonr':lonr,'lonu':lonu,'lonv':lonv,'lonpsi':lonpsi,
            'latr':latr,'latu':latu,'latv':yv,'latpsi':latpsi,
            'Cs_r':Cs_r,'sc_r':sc_r,'hc':hc,'h':h, 
            'theta_s':theta_s,'theta_b':theta_b,
            'basemap':basemap}
    else:
        grid = {'imt':imt,'jmt':jmt, 
            'dxv':dxv,'dyu':dyu,'dxdy':dxdy, 
            'mask':mask,
            'pm':pm,'pn':pn,'tri':tri,'trir':trir,'trirllrho':trirllrho,
            'xr':xr,'xu':xu,'xv':xv,'xpsi':xpsi,'X':X,
            'yr':yr,'yu':yu,'yv':yv,'ypsi':ypsi,'Y':Y,
            'lonr':lonr,'lonu':lonu,'lonv':lonv,'lonpsi':lonpsi,
            'latr':latr,'latu':latu,'latv':yv,'latpsi':latpsi,
            'h':h, 
            'basemap':basemap}
 
    gridfile.close()

    return grid
Example #6
0
def setupROMSfiles(loc,date,ff,tout, tstride=1):
    '''
    setupROMSfiles()
    Kristen Thyng, March 2013

    Figures out necessary files to read in for track times and what
    model output indices within those files to use.

    Input:
     loc        File location. loc can be:
                * a thredds server web address
                * a single string of a file location
                * a list of strings of multiple file locations to be searched
                through
     date       datetime format start date
     ff         Time direction. ff=1 forward, ff=-1 backward
     tout       Number of model outputs to use
     tstride    Stride in time, in case want to use less model output
                 than is available. Default is 1, using all output.

    Output:
     nc         NetCDF object for relevant files
     tinds      Indices of outputs to use from fname files
    '''
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here: 
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')

    # For thredds server where all information is available in one place
    # or for a single file
    if 'http' in loc or type(loc)==str:
        nc = netCDF.Dataset(loc)
        if ff == 1: #forward in time
            dates = nc.variables['ocean_time'][:] # don't stride here, need all times to make index determinations
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart,istart+tout, tstride) #use tstride here to get tinds correct
        else: #backward
            dates = nc.variables['ocean_time'][:]   
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart,istart-tout, -tstride) #use tstride here to get tinds correct

    # This is for the case when we have a bunch of files to sort through
    else:
        # the globbing should happen ahead of time so this case looks different than
        # the single file case
        # files = np.sort(glob.glob(loc)) # sorted list of file names
        files = loc # file list is now to be input
        # pdb.set_trace()
        # Find the list of files that cover the desired time period
        # First, check to see if there is one or more than one time index in each file because
        # if there is only one, we need to compare two files to see where we are in time
        # So, open the first file to check.
        nctemp = netCDF.Dataset(files[0])
        ttemp = nctemp.variables['ocean_time'][:]
        nctemp.close()
        if ttemp.size==1: # one output/time step per file. 
            noutputs = 1
            # Assume it is safe to open them all to search for starting place. Rest of indices
            # are checked below.
            nctemp = netCDF.MFDataset(files)
            ttemp = nctemp.variables['ocean_time'][:]
            nctemp.close()
            # find which time steps date is between and take earlier one as the starting file
            ifile = find(ttemp<=date)[0]

        else: # more than one output per file  
            noutputs = 0          
            for i,name in enumerate(files): # Loop through files
                nctemp = netCDF.Dataset(name)
                ttemp = nctemp.variables['ocean_time'][:]
                # pdb.set_trace()
                nctemp.close()
                # need to check subsequent file as well, in case starting time is between files
                if i<(len(files)-1):
                    nctemp2 = netCDF.Dataset(files[i+1])
                    ttemp2 = nctemp2.variables['ocean_time'][:]
                    nctemp2.close()
                # If datenum_in is larger than the first time in the file but smaller
                # than the last time, then this is the correct file to use to start
                # or, if the starting date is between this file and the next, start 
                # with this file (for interpolation between the outputs)
                if (date >= ttemp[0] and date <= ttemp[-1]) or (date>ttemp[-1] and date<ttemp2[0]):
                    ifile = i # this is the starting file identifier then
                    break

        # Since the number of indices per file can change, make the process
        # of finding the necessary files a little more general
        # Start by opening two files
        i = 1
        fname = [files[ifile]]

        nc = netCDF.MFDataset(fname) # files in fname are in chronological order
        # Find which output in ifile is closest to the user-input start time (choose lower index)
        # Dates for drifters from this start date
        dates = nc.variables['ocean_time'][:]   
        ilow = date >= dates
        # time index with time value just below date (relative to file ifile)
        istart = dates[ilow].size - 1
        nc.close()
        # Select indices 
        if ff==1:
            tinds = range(istart,istart+tout, tstride) # indices of model outputs desired
        else: # backward in time
            # have to shift istart since there are now new indices behind since going backward
            tinds = range(istart,istart-tout, -tstride)
        # If we need more indices than available in these files, add another

        if ff==1:
            # If there is one output per file, just grab the number of necessary files
            if noutputs:
                fname = files[ifile:ifile+tout]
                nc = netCDF.MFDataset(fname) # files in fname are in chronological order

            else: # multiple snapshots per file
                # pdb.set_trace()
                # if the final index we want is beyond the length of these files,
                # keep adding files on
                # need an extra index for interpolation
                while tinds[-1]+1 > len(dates):
                # while len(tinds)+1 > len(dates): 
                    # if tdir: #forward - add 2nd file on end
                    fname.append(files[ifile+i])
                    nc = netCDF.MFDataset(fname) # files in fname are in chronological order
                    dates = nc.variables['ocean_time'][:]   
                    # ilow = date >= dates
                    # # time index with time value just below datenum_in (relative to file ifile)
                    # istart = dates[ilow].size - 1
                    # tinds = range(istart,istart+tout, tstride)
                    nc.close()
                    i = i + 1

        else: #backwards in time
            while tinds[-1] < 0:
                fname.insert(0,files[ifile-i])
                nc = netCDF.MFDataset(fname)
                dates = nc.variables['ocean_time'][:]   
                ilow = date >= dates
                # time index with time value just below datenum_in (relative to file ifile)
                istart = dates[ilow].size - 1
                tinds = range(istart,istart-tout, -tstride)
                nc.close()
                i = i + 1
        
        # model output files together containing all necessary model outputs
        nc = netCDF.MFDataset(fname) # reopen since needed to close things in loop

    return nc, tinds
Example #7
0
def readgrid(grid_filename, vert_filename=None, llcrnrlon=-98.5, llcrnrlat=22.5, 
            urcrnrlon=-87.5, urcrnrlat=31.0, lat_0=30, lon_0=-94, res='i', 
            usebasemap=False, usespherical=True):
    '''
    readgrid(loc)
    Kristen Thyng, March 2013
    This function should be read in at the beginnind of a run.py call.
    It reads in all necessary grid information that won't change in time
    and stores it in a dictionary called grid.
    All arrays are changed to Fortran ordering (from Python ordering)
    and to tracmass variables ordering from ROMS ordering 
    i.e. from [t,k,j,i] to [i,j,k,t]
    right away after reading in.

    Input:
     grid_filename    File name (with extension) where grid information is stored
     vert_filename    (optional) File name (with extension) where vertical grid information
                    is stored, if not in grid_loc. Can also skip this if don't need 
                    vertical grid info.
     also optional basemap box parameters. Default is for full shelf model.
     usebasemap          (False) Whether to use load basemap into grid (True) or pyproj (False).
                    Basemap is slower but can be used for plotting, and pyproj is the opposite.

    Output:
     grid           Dictionary containing all necessary time-independent grid fields

    grid dictionary contains: (array sizing is for tracmass ordering)
     imt,jmt,km     Grid index sizing constants in (x,y,z), are for horizontal rho grid [scalar]
     dxv            Horizontal grid cell walls areas in x direction [imt,jmt-1]
     dyu            Horizontal grid cell walls areas in y direction [imt-1,jmt]
     dxdy           Horizontal area of cells defined at cell centers [imt,jmt]
     mask           Land/sea mask [imt,jmt] 
     pm,pn          Difference in horizontal grid spacing in x and y [imt,jmt]
     kmt            Number of vertical levels in horizontal space [imt,jmt]
     dzt0           Thickness in meters of grid at each k-level with time-independent free surface. 
                    Surface is at km [imt,jmt,km].
     zrt0           Depth in meters of grid at each k-level on vertical rho grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     zwt0           Depth in meters of grid at each k-level on vertical w grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     xr,yr          Rho grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xu,yu          U grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xv,yv          V grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xpsi,ypsi      Psi grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     X,Y            Grid index arrays
     tri,trir       Delaunay triangulations
     Cs_r,sc_r      Vertical grid streching paramters [km-1]
     hc             Critical depth [scalar]
     h              Depths [imt,jmt]
     theta_s        Vertical stretching parameter [scalar]. A parameter 
                    (typically 0.0 <= theta_s < 5.0) that defines the amount 
                    of grid focusing. A higher value for theta_s will focus the grid more.
     theta_b        Vertical stretching parameter [scalar]. A parameter (0.0 < theta_b < 1.0) 
                    that says whether the coordinate will be focused at the surface 
                    (theta_b -> 1.0) or split evenly between surface and bottom (theta_b -> 0)
     basemap        Basemap object

    Note: all are in fortran ordering and tracmass ordering except for X, Y, tri, and tric
    To test: [array].flags['F_CONTIGUOUS'] will return true if it is fortran ordering
    '''
    keeptime = 0 # do timing for readgrid
    if keeptime: starttime = time.time()

    # Read in grid parameters and find x and y in domain on different grids
    # use full dataset to get grid information
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here:
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')
    gridfile = netCDF.Dataset(grid_filename)

    # # Read in whether grid is spherical or not
    # try:
    #     usesphericaltemp = gridfile.variables['spherical'][:]
    #     if usesphericaltemp == 'T':
    #         usespherical = True
    #     else:
    #         usespherical = False
    # except KeyError: # Assume not lon/lat if spherical flag is not in grid file
    #     usespherical = False

    # Basemap parameters.
    if usespherical:
        llcrnrlon=llcrnrlon; llcrnrlat=llcrnrlat; 
        urcrnrlon=urcrnrlon; urcrnrlat=urcrnrlat; projection='lcc'
        lat_0=lat_0; lon_0=lon_0; resolution=res; area_thresh=0.
        # pdb.set_trace()
        if usebasemap:
            from mpl_toolkits.basemap import Basemap
            basemap = Basemap(llcrnrlon=llcrnrlon,
                         llcrnrlat=llcrnrlat,
                         urcrnrlon=urcrnrlon,
                         urcrnrlat=urcrnrlat,
                         projection=projection,
                         lat_0=lat_0,
                         lon_0=lon_0,
                         resolution=resolution,
                         area_thresh=area_thresh)
        else:
            from pyproj import Proj
            # this gives somewhat different differences between projected coordinates as compared with previous basemap
            # definition for the default values.
            basemap = Proj(proj='lcc', lat_1=llcrnrlat, lat_2=urcrnrlat, lat_0=lat_0, lon_0=lon_0, x_0=0, y_0=0,ellps='clrk66',datum='NAD27')
            # basemap = (proj='lcc',lat_1=44.33333333333334,lat_2=46,lat_0=43.66666666666666, lon_0=-120.5,x_0=609601.2192024384, y_0=0,ellps='clrk66',datum='NAD27')
            # basemap = Proj("+proj=lcc +lat_0=lat_0 +lon_0=lon_0")
                            # +x_0=1700000 \
                            # +y_0=300000 \
                            # +no_defs \
                            # +a=6378137 \
                            # +rf=298.257222101 \
                            # +to_meter=1")
        if keeptime: 
            basemaptime = time.time()
            print "basemap time ", basemaptime - starttime
    else:
        basemap = []

    if usespherical:
        lonu = gridfile.variables['lon_u'][:]
        latu = gridfile.variables['lat_u'][:]
        xu, yu = basemap(lonu,latu)
        lonv = gridfile.variables['lon_v'][:]
        latv = gridfile.variables['lat_v'][:]
        xv, yv = basemap(lonv,latv)
        lonr = gridfile.variables['lon_rho'][:]#[1:-1,1:-1]
        latr = gridfile.variables['lat_rho'][:]#[1:-1,1:-1]
        xr, yr = basemap(lonr,latr)
        lonpsi = gridfile.variables['lon_psi'][:]
        latpsi = gridfile.variables['lat_psi'][:]
        xpsi, ypsi = basemap(lonpsi,latpsi)
    else:
        # read cartesian data
        xu = gridfile.variables['x_u'][:]
        yu = gridfile.variables['y_u'][:]
        xv = gridfile.variables['x_v'][:]
        yv = gridfile.variables['y_v'][:]
        xr = gridfile.variables['x_rho'][:]
        yr = gridfile.variables['y_rho'][:]
        xpsi = gridfile.variables['x_psi'][:]
        ypsi = gridfile.variables['y_psi'][:]

        # assign to spherical arrays
        lonu, latu = xu, yu
        lonv, latv = xv, yv
        lonr, latr = xr, yr
        lonpsi, latpsi = xpsi, ypsi

    # Create mask of all active cells if there isn't one already
    try:
        mask = gridfile.variables['mask_rho'][:]#[1:-1,1:-1]
    except KeyError:
        mask = np.ones_like(xr)

    pm = gridfile.variables['pm'][:]
    pn = gridfile.variables['pn'][:]
    h = gridfile.variables['h'][:]
    if keeptime:
        hgridtime = time.time()
        print "horizontal grid time ", hgridtime - basemaptime

    # Vertical grid metrics
    if 's_w' in gridfile.variables: # then given grid file contains vertical grid info
        sc_r = gridfile.variables['s_w'][:] # sigma coords, 31 layers
        Cs_r = gridfile.variables['Cs_w'][:] # stretching curve in sigma coords, 31 layers
        hc = gridfile.variables['hc'][:]
        theta_s = gridfile.variables['theta_s'][:]
        theta_b = gridfile.variables['theta_b'][:]
        Vtransform = gridfile.variables['Vtransform'][:]
        Vstretching = gridfile.variables['Vstretching'][:]
    # Still want vertical grid metrics, but are in separate file
    elif vert_filename is not None:
        nc = netCDF.Dataset(vert_filename)
        sc_r = nc.variables['s_w'][:] # sigma coords, 31 layers
        Cs_r = nc.variables['Cs_w'][:] # stretching curve in sigma coords, 31 layers
        hc = nc.variables['hc'][:]
        theta_s = nc.variables['theta_s'][:]
        theta_b = nc.variables['theta_b'][:]
        Vtransform = nc.variables['Vtransform'][:]
        Vstretching = nc.variables['Vstretching'][:]

    if keeptime: 
        vgridtime = time.time()
        print "vertical grid time ", vgridtime - hgridtime

    # make arrays in same order as is expected in the fortran code
    # ROMS expects [time x k x j x i] but tracmass is expecting [i x j x k x time]
    # change these arrays to be fortran-directioned instead of python
    # This is faster than copying arrays. To test: .flags['F_CONTIGUOUS']
    mask = np.asfortranarray(mask.T)
    xr = np.asfortranarray(xr.T)
    yr = np.asfortranarray(yr.T)
    xu = np.asfortranarray(xu.T)
    yu = np.asfortranarray(yu.T)
    xv = np.asfortranarray(xv.T)
    yv = np.asfortranarray(yv.T)
    xpsi = np.asfortranarray(xpsi.T)
    ypsi = np.asfortranarray(ypsi.T)
    lonr = np.asfortranarray(lonr.T)

    latr = np.asfortranarray(latr.T)
    lonu = np.asfortranarray(lonu.T)
    latu = np.asfortranarray(latu.T)
    lonv = np.asfortranarray(lonv.T)
    latv = np.asfortranarray(latv.T)
    lonpsi = np.asfortranarray(lonpsi.T)
    latpsi = np.asfortranarray(latpsi.T)
    pm = np.asfortranarray(pm.T)
    pn = np.asfortranarray(pn.T)
    h = np.asfortranarray(h.T)

    if keeptime: 
        fortranflippingtime = time.time()
        print "fortran flipping time ", fortranflippingtime - vgridtime

    # Basing this on setupgrid.f95 for rutgersNWA example project from Bror
    # Grid sizes
    imt = h.shape[0] # 671
    jmt = h.shape[1] # 191
    if 'sc_r' in dir():
        km = sc_r.shape[0]-1 # 30 NOT SURE ON THIS ONE YET

    if keeptime: 
        gridsizetime = time.time()
        print "grid size time ", gridsizetime - fortranflippingtime

    # Index grid, for interpolation between real and grid space
    # this is for psi grid, so that middle of grid is min + .5 value
    # # X goes from 0 to imt-2 and Y goes from 0 to jmt-2
    # Y, X = np.meshgrid(np.arange(jmt-1),np.arange(imt-1)) # grid in index coordinates, without ghost cells
    # This is for rho
    # X goes from 0 to imt-1 and Y goes from 0 to jmt-1
    Y, X = np.meshgrid(np.arange(jmt),np.arange(imt)) # grid in index coordinates, without ghost cells
    # Triangulation for grid space to curvilinear space
    tri = delaunay.Triangulation(X.flatten(),Y.flatten())
    # Triangulation for curvilinear space to grid space
    # pdb.set_trace()
    trir = delaunay.Triangulation(xr.flatten(),yr.flatten())
    trirllrho = delaunay.Triangulation(lonr.flatten(),latr.flatten())

    if keeptime: 
        delaunaytime = time.time()
        print "delaunay time ", delaunaytime - gridsizetime

    # tracmass ordering.
    # Not sure how to convert this to pm, pn with appropriate shift
    dxv = 1/pm # pm is 1/\Delta x at cell centers
    dyu = 1/pn # pn is 1/\Delta y at cell centers

    dxdy = dyu*dxv

    # Change dxv,dyu to be correct u and v grid size after having 
    # them be too big for dxdy calculation. This is not in the 
    # rutgersNWA example and I am not sure why. [i,j]
    dxv = 0.5*(dxv[:,:-1]+dxv[:,1:])
    dyu = 0.5*(dyu[:-1,:]+dyu[1:,:])
    # # These should be interpolated
    # dxv = dxv[:,:-1]
    # dyu = dyu[:-1,:]

    if keeptime: 
        gridmetricstime = time.time()
        print "grid metrics time ", gridmetricstime - delaunaytime

    # Adjust masking according to setupgrid.f95 for rutgersNWA example project from Bror
    if 'sc_r' in dir():
        mask2 = mask.copy()
        kmt = np.ones((imt,jmt),order='f')*km
        ind = (mask2==1)
        ind[0:imt-1,:] = ind[1:imt,:]
        mask2[ind] = 1
        ind = (mask2==1)
        ind[:,0:jmt-1] = ind[:,1:jmt]
        mask2[ind] = 1
        # ind = (mask[1:imt-1,:]==1)
        # mask[0:imt-2,ind] = 1
        # ind = (mask[:,1:imt-1]==1)
        # mask[:,0:jmt-2] = 1
        ind = (mask2==0)
        kmt[ind] = 0

        # Use octant to calculate depths/thicknesses for the appropriate vertical grid parameters
        # have to transform a few back to ROMS coordinates and python ordering for this
        zwt0 = octant.depths.get_zw(Vtransform, Vstretching, km+1, theta_s, theta_b, 
                        h.T.copy(order='c'), 
                        hc, zeta=0, Hscale=3)
        zrt0 = octant.depths.get_zrho(Vtransform, Vstretching, km, theta_s, theta_b, 
                        h.T.copy(order='c'), 
                        hc, zeta=0, Hscale=3)
        # Change dzt to tracmass/fortran ordering
        zwt0 = zwt0.T.copy(order='f')
        zrt0 = zrt0.T.copy(order='f')
        # this should be the base grid layer thickness that doesn't change in time because it 
        # is for the reference vertical level
        dzt0 = zwt0[:,:,1:] - zwt0[:,:,:-1]

    if keeptime: 
        calculatingdepthstime = time.time()
        print "calculating depths time ", calculatingdepthstime - gridmetricstime

    # Fill in grid structure
    if 'sc_r' in dir():
        grid = {'imt':imt,'jmt':jmt,'km':km,#'angle':angle, 
            'dxv':dxv,'dyu':dyu,'dxdy':dxdy, 
            'mask':mask,'kmt':kmt,'dzt0':dzt0,
            'zrt0':zrt0,'zwt0':zwt0,
            'pm':pm,'pn':pn,'tri':tri,'trir':trir,'trirllrho':trirllrho,
            'xr':xr,'xu':xu,'xv':xv,'xpsi':xpsi,'X':X,
            'yr':yr,'yu':yu,'yv':yv,'ypsi':ypsi,'Y':Y,
            'lonr':lonr,'lonu':lonu,'lonv':lonv,'lonpsi':lonpsi,
            'latr':latr,'latu':latu,'latv':yv,'latpsi':latpsi,
            'Cs_r':Cs_r,'sc_r':sc_r,'hc':hc,'h':h, 
            'theta_s':theta_s,'theta_b':theta_b,
            'Vtransform':Vtransform, 'Vstretching':Vstretching,
            'basemap':basemap}
    else:
        grid = {'imt':imt,'jmt':jmt, #'angle':angle,
            'dxv':dxv,'dyu':dyu,'dxdy':dxdy, 
            'mask':mask,
            'pm':pm,'pn':pn,'tri':tri,'trir':trir,'trirllrho':trirllrho,
            'xr':xr,'xu':xu,'xv':xv,'xpsi':xpsi,'X':X,
            'yr':yr,'yu':yu,'yv':yv,'ypsi':ypsi,'Y':Y,
            'lonr':lonr,'lonu':lonu,'lonv':lonv,'lonpsi':lonpsi,
            'latr':latr,'latu':latu,'latv':yv,'latpsi':latpsi,
            'h':h, 
            'basemap':basemap}
 
    if keeptime: 
        griddicttime = time.time()
        print "saving grid dict time ", griddicttime - calculatingdepthstime

    gridfile.close()

    return grid
Example #8
0
def setupROMSfiles(loc, date, ff, tout, tstride=1):
    '''
    setupROMSfiles()
    Kristen Thyng, March 2013

    Figures out necessary files to read in for track times and what
    model output indices within those files to use.

    Input:
     loc        File location
     date       datetime format start date
     ff         Time direction. ff=1 forward, ff=-1 backward
     tout       Number of model outputs to use
     tstride    Stride in time, in case want to use less model output
                 than is available. Default is 1, using all output.

    Output:
     nc         NetCDF object for relevant files
     tinds      Indices of outputs to use from fname files
    '''
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here:
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')

    # pdb.set_trace()
    if 'http' in loc or (len(loc) == 2
                         and '.nc' in loc[0]):  # use just input file
        if len(loc) == 2:
            nc = netCDF.Dataset(loc[0])
        else:
            nc = netCDF.Dataset(loc)
        if ff == 1:  #forward in time
            dates = nc.variables[
                'ocean_time'][:]  # don't stride here, need all times to make index determinations
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart, istart + tout,
                          tstride)  #use tstride here to get tinds correct
        else:  #backward
            dates = nc.variables['ocean_time'][:]
            ilow = date >= dates
            # time index with time value just below datenum_in (relative to file ifile)
            istart = dates[ilow].size - 1
            tinds = range(istart, istart - tout,
                          -tstride)  #use tstride here to get tinds correct

    # This is for the case when we have a bunch of files to sort through
    else:
        if len(loc) == 2:
            files = np.sort(
                glob.glob(loc[0] +
                          'ocean_his_????.nc'))  # sorted list of file names
        else:
            files = np.sort(
                glob.glob(loc +
                          'ocean_his_????.nc'))  # sorted list of file names
        # files = np.sort(glob.glob(loc + 'ocean_his_*_tochange.nc')) # this is for idealized tests

        # Find the list of files that cover the desired time period
        for i, name in enumerate(files):  # Loop through files
            nctemp = netCDF.Dataset(name)
            ttemp = nctemp.variables['ocean_time'][:]
            # pdb.set_trace()
            nctemp.close()
            # If datenum_in is larger than the first time in the file but smaller
            # than the last time, then this is the correct file to use to start
            if date >= ttemp[0] and date <= ttemp[-1]:
                ifile = i  # this is the starting file identifier then
                break

        # Since the number of indices per file can change, make the process
        # of finding the necessary files a little more general
        # Start by opening two files
        i = 1
        # pdb.set_trace()
        fname = [files[ifile]]

        nc = netCDF.MFDataset(
            fname)  # files in fname are in chronological order
        # # number of indices included in opened files so far
        # ninds = nc.variables['ocean_time'][:].size
        # Find which output in ifile is closest to the user-input start time (choose lower index)
        # Dates for drifters from this start date
        dates = nc.variables['ocean_time'][:]
        ilow = date >= dates
        # time index with time value just below date (relative to file ifile)
        istart = dates[ilow].size - 1
        nc.close()
        # Select indices
        if ff == 1:
            tinds = range(istart, istart + tout,
                          tstride)  # indices of model outputs desired
        else:  # backward in time
            # have to shift istart since there are now new indices behind since going backward
            tinds = range(istart, istart - tout, -tstride)
        # If we need more indices than available in these files, add another

        if ff == 1:
            # if the final index we want is beyond the length of these files,
            # keep adding files on
            while tinds[-1] > len(dates):
                # if tdir: #forward - add 2nd file on end
                fname.append(files[ifile + i])
                nc = netCDF.MFDataset(
                    fname)  # files in fname are in chronological order
                dates = nc.variables['ocean_time'][:]
                ilow = date >= dates
                # time index with time value just below datenum_in (relative to file ifile)
                istart = dates[ilow].size - 1
                tinds = range(istart, istart + tout, tstride)
                nc.close()
                i = i + 1
        else:  #backwards in time
            while tinds[-1] < 0:
                fname.insert(0, files[ifile - i])
                nc = netCDF.MFDataset(fname)
                dates = nc.variables['ocean_time'][:]
                ilow = date >= dates
                # time index with time value just below datenum_in (relative to file ifile)
                istart = dates[ilow].size - 1
                tinds = range(istart, istart - tout, -tstride)
                nc.close()
                i = i + 1

        # model output files together containing all necessary model outputs
        nc = netCDF.MFDataset(
            fname)  # reopen since needed to close things in loop
    # pdb.set_trace()
    return nc, tinds
Example #9
0
def readgrid(loc,
             nc=None,
             llcrnrlon=-98.5,
             llcrnrlat=22.5,
             urcrnrlon=-87.5,
             urcrnrlat=31.0,
             res='i'):
    '''
    readgrid(loc)
    Kristen Thyng, March 2013
    This function should be read in at the beginnind of a run.py call.
    It reads in all necessary grid information that won't change in time
    and stores it in a dictionary called grid.
    All arrays are changed to Fortran ordering (from Python ordering)
    and to tracmass variables ordering from ROMS ordering 
    i.e. from [t,k,j,i] to [i,j,k,t]
    right away after reading in.

    Input:
     loc            File location
     nc             (optional) NetCDF object for relevant files
     also optional basemap box parameters. Default is for full shelf model.


    Output:
     grid           Dictionary containing all necessary time-independent grid fields

    grid dictionary contains: (array sizing is for tracmass ordering)
     imt,jmt,km     Grid index sizing constants in (x,y,z), are for horizontal rho grid [scalar]
     dxv            Horizontal grid cell walls areas in x direction [imt,jmt-1]
     dyu            Horizontal grid cell walls areas in y direction [imt-1,jmt]
     dxdy           Horizontal area of cells defined at cell centers [imt,jmt]
     mask           Land/sea mask [imt,jmt] 
     pm,pn          Difference in horizontal grid spacing in x and y [imt,jmt]
     kmt            Number of vertical levels in horizontal space [imt,jmt]
     dzt0           Thickness in meters of grid at each k-level with time-independent free surface. 
                    Surface is at km [imt,jmt,km].
     zrt0           Depth in meters of grid at each k-level on vertical rho grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     zwt0           Depth in meters of grid at each k-level on vertical w grid with time-independent 
                    free surface. Surface is at km [imt,jmt,km]
     xr,yr          Rho grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xu,yu          U grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xv,yv          V grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     xpsi,ypsi      Psi grid zonal (x) and meriodional (y) coordinates [imt,jmt]
     X,Y            Grid index arrays
     tri,trir       Delaunay triangulations
     Cs_r,sc_r      Vertical grid streching paramters [km-1]
     hc             Critical depth [scalar]
     h              Depths [imt,jmt]
     theta_s        Vertical stretching parameter [scalar]. A parameter 
                    (typically 0.0 <= theta_s < 5.0) that defines the amount 
                    of grid focusing. A higher value for theta_s will focus the grid more.
     theta_b        Vertical stretching parameter [scalar]. A parameter (0.0 < theta_b < 1.0) 
                    that says whether the coordinate will be focused at the surface 
                    (theta_b -> 1.0) or split evenly between surface and bottom (theta_b -> 0)
     basemap        Basemap object

    Note: all are in fortran ordering and tracmass ordering except for X, Y, tri, and tric
    To test: [array].flags['F_CONTIGUOUS'] will return true if it is fortran ordering
    '''

    # Basemap parameters.
    llcrnrlon = llcrnrlon
    llcrnrlat = llcrnrlat
    urcrnrlon = urcrnrlon
    urcrnrlat = urcrnrlat
    projection = 'lcc'
    lat_0 = 30
    lon_0 = -94
    resolution = res
    area_thresh = 0.
    basemap = Basemap(llcrnrlon=llcrnrlon,
                      llcrnrlat=llcrnrlat,
                      urcrnrlon=urcrnrlon,
                      urcrnrlat=urcrnrlat,
                      projection=projection,
                      lat_0=lat_0,
                      lon_0=lon_0,
                      resolution=resolution,
                      area_thresh=area_thresh)

    # Read in grid parameters and find x and y in domain on different grids
    # if len(loc) == 2:
    #   gridfile = netCDF.Dataset(loc[1])
    # use full dataset to get grid information
    # This addresses an issue in netCDF4 that was then fixed, but
    # this line makes updating unnecessary. Issue described here:
    # http://code.google.com/p/netcdf4-python/issues/detail?id=170
    netCDF._set_default_format(format='NETCDF3_64BIT')
    # pdb.set_trace()
    # grid is included in nc file if using thredds or forecast output
    if 'http' in loc:
        gridfile = netCDF.Dataset(loc)
    elif len(loc) == 2:
        gridfile = netCDF.Dataset(loc[1])
    else:
        gridfile = netCDF.Dataset(loc + 'grid.nc')
    lonu = gridfile.variables['lon_u'][:]
    latu = gridfile.variables['lat_u'][:]
    xu, yu = basemap(lonu, latu)
    lonv = gridfile.variables['lon_v'][:]
    latv = gridfile.variables['lat_v'][:]
    xv, yv = basemap(lonv, latv)
    lonr = gridfile.variables['lon_rho'][:]  #[1:-1,1:-1]
    latr = gridfile.variables['lat_rho'][:]  #[1:-1,1:-1]
    xr, yr = basemap(lonr, latr)
    lonpsi = gridfile.variables['lon_psi'][:]
    latpsi = gridfile.variables['lat_psi'][:]
    xpsi, ypsi = basemap(lonpsi, latpsi)
    mask = gridfile.variables['mask_rho'][:]  #[1:-1,1:-1]
    pm = gridfile.variables['pm'][:]
    pn = gridfile.variables['pn'][:]
    h = gridfile.variables['h'][:]
    angle = gridfile.variables['angle'][:]

    # Vertical grid metrics
    if 'http' in loc or len(loc) == 2 or 's_w' in gridfile.variables:
        sc_r = gridfile.variables['s_w'][:]  # sigma coords, 31 layers
        Cs_r = gridfile.variables[
            'Cs_w'][:]  # stretching curve in sigma coords, 31 layers
        hc = gridfile.variables['hc'][:]
        theta_s = gridfile.variables['theta_s'][:]
        theta_b = gridfile.variables['theta_b'][:]
        Vtransform = gridfile.variables['Vtransform'][0]
        Vstretching = gridfile.variables['Vstretching'][0]
    elif nc is not None:  # for if running off local grid/nc files
        sc_r = nc.variables['s_w'][:]  # sigma coords, 31 layers
        Cs_r = nc.variables[
            'Cs_w'][:]  # stretching curve in sigma coords, 31 layers
        hc = nc.variables['hc'][:]
        theta_s = nc.variables['theta_s'][:]
        theta_b = nc.variables['theta_b'][:]
        Vtransform = nc.variables['Vtransform'][:]
        Vstretching = nc.variables['Vstretching'][:]

    # make arrays in same order as is expected in the fortran code
    # ROMS expects [time x k x j x i] but tracmass is expecting [i x j x k x time]
    # change these arrays to be fortran-directioned instead of python
    # tic = time.time()
    # This is faster than copying arrays. To test: .flags['F_CONTIGUOUS']
    mask = np.asfortranarray(mask.T)
    xr = np.asfortranarray(xr.T)
    yr = np.asfortranarray(yr.T)
    xu = np.asfortranarray(xu.T)
    yu = np.asfortranarray(yu.T)
    xv = np.asfortranarray(xv.T)
    yv = np.asfortranarray(yv.T)
    xpsi = np.asfortranarray(xpsi.T)
    ypsi = np.asfortranarray(ypsi.T)
    lonr = np.asfortranarray(lonr.T)

    latr = np.asfortranarray(latr.T)
    lonu = np.asfortranarray(lonu.T)
    latu = np.asfortranarray(latu.T)
    lonv = np.asfortranarray(lonv.T)
    latv = np.asfortranarray(latv.T)
    lonpsi = np.asfortranarray(lonpsi.T)
    latpsi = np.asfortranarray(latpsi.T)
    pm = np.asfortranarray(pm.T)
    pn = np.asfortranarray(pn.T)
    h = np.asfortranarray(h.T)
    # print "fortran time ",time.time()-tic
    # pdb.set_trace()

    # Basing this on setupgrid.f95 for rutgersNWA example project from Bror
    # Grid sizes
    imt = h.shape[0]  # 671
    jmt = h.shape[1]  # 191
    # km = sc_r.shape[0] # 31
    if ('http' in loc) or (
            nc is not None) or len(loc) == 2 or 's_w' in gridfile.variables:
        km = sc_r.shape[0] - 1  # 30 NOT SURE ON THIS ONE YET

    # Index grid, for interpolation between real and grid space
    # this is for psi grid, so that middle of grid is min + .5 value
    # # X goes from 0 to imt-2 and Y goes from 0 to jmt-2
    # Y, X = np.meshgrid(np.arange(jmt-1),np.arange(imt-1)) # grid in index coordinates, without ghost cells
    # This is for rho
    # X goes from 0 to imt-1 and Y goes from 0 to jmt-1
    Y, X = np.meshgrid(
        np.arange(jmt),
        np.arange(imt))  # grid in index coordinates, without ghost cells
    # Triangulation for grid space to curvilinear space
    tri = delaunay.Triangulation(X.flatten(), Y.flatten())
    # Triangulation for curvilinear space to grid space
    # pdb.set_trace()
    trir = delaunay.Triangulation(xr.flatten(), yr.flatten())
    trirllrho = delaunay.Triangulation(lonr.flatten(), latr.flatten())

    # tracmass ordering.
    # Not sure how to convert this to pm, pn with appropriate shift
    dxv = 1 / pm  #.copy() # pm is 1/\Delta x at cell centers
    dyu = 1 / pn  #.copy() # pn is 1/\Delta y at cell centers

    # dxv = xr.copy()
    # dxv[0:imt-2,:] = dxv[1:imt-1,:] - dxv[0:imt-2,:]
    # dxv[imt-1:imt,:] = dxv[imt-3:imt-2,:]
    # # pdb.set_trace()
    # dyu = yr.copy()
    # dyu[:,0:jmt-2] = dyu[:,1:jmt-1] - dyu[:,0:jmt-2]
    # dyu[:,jmt-1] = dyu[:,jmt-2]
    dxdy = dyu * dxv

    # Change dxv,dyu to be correct u and v grid size after having
    # them be too big for dxdy calculation. This is not in the
    # rutgersNWA example and I am not sure why. [i,j]
    dxv = 0.5 * (dxv[:, :-1] + dxv[:, 1:])
    dyu = 0.5 * (dyu[:-1, :] + dyu[1:, :])
    # # These should be interpolated
    # dxv = dxv[:,:-1]
    # dyu = dyu[:-1,:]

    # Adjust masking according to setupgrid.f95 for rutgersNWA example project from Bror
    # pdb.set_trace()
    if ('http' in loc) or (
            nc is not None) or len(loc) == 2 or 's_w' in gridfile.variables:
        mask2 = mask.copy()
        kmt = np.ones((imt, jmt), order='f') * km
        ind = (mask2[1:imt, :] == 1)
        mask2[0:imt - 1, ind] = 1
        ind = (mask2[:, 1:jmt] == 1)
        mask2[ind, 0:jmt - 1] = 1
        # ind = (mask[1:imt-1,:]==1)
        # mask[0:imt-2,ind] = 1
        # ind = (mask[:,1:imt-1]==1)
        # mask[:,0:jmt-2] = 1
        ind = (mask2 == 0)
        kmt[ind] = 0

        # Use octant to calculate depths/thicknesses for the appropriate vertical grid parameters
        # have to transform a few back to ROMS coordinates and python ordering for this
        zwt0 = octant.depths.get_zw(Vtransform,
                                    Vstretching,
                                    km + 1,
                                    theta_s,
                                    theta_b,
                                    h.T.copy(order='c'),
                                    hc,
                                    zeta=0,
                                    Hscale=3)
        zrt0 = octant.depths.get_zrho(Vtransform,
                                      Vstretching,
                                      km,
                                      theta_s,
                                      theta_b,
                                      h.T.copy(order='c'),
                                      hc,
                                      zeta=0,
                                      Hscale=3)
        # Change dzt to tracmass/fortran ordering
        zwt0 = zwt0.T.copy(order='f')
        zrt0 = zrt0.T.copy(order='f')
        # this should be the base grid layer thickness that doesn't change in time because it
        # is for the reference vertical level
        dzt0 = zwt0[:, :, 1:] - zwt0[:, :, :-1]

    # Fill in grid structure
    if ('http' in loc) or (
            nc is not None) or len(loc) == 2 or 's_w' in gridfile.variables:
        grid = {
            'imt': imt,
            'jmt': jmt,
            'km': km,
            'angle': angle,
            'dxv': dxv,
            'dyu': dyu,
            'dxdy': dxdy,
            'mask': mask,
            'kmt': kmt,
            'dzt0': dzt0,
            'zrt0': zrt0,
            'zwt0': zwt0,
            'pm': pm,
            'pn': pn,
            'tri': tri,
            'trir': trir,
            'trirllrho': trirllrho,
            'xr': xr,
            'xu': xu,
            'xv': xv,
            'xpsi': xpsi,
            'X': X,
            'yr': yr,
            'yu': yu,
            'yv': yv,
            'ypsi': ypsi,
            'Y': Y,
            'lonr': lonr,
            'lonu': lonu,
            'lonv': lonv,
            'lonpsi': lonpsi,
            'latr': latr,
            'latu': latu,
            'latv': yv,
            'latpsi': latpsi,
            'Cs_r': Cs_r,
            'sc_r': sc_r,
            'hc': hc,
            'h': h,
            'theta_s': theta_s,
            'theta_b': theta_b,
            'Vtransform': Vtransform,
            'Vstretching': Vstretching,
            'basemap': basemap
        }
    else:
        grid = {
            'imt': imt,
            'jmt': jmt,
            'angle': angle,
            'dxv': dxv,
            'dyu': dyu,
            'dxdy': dxdy,
            'mask': mask,
            'pm': pm,
            'pn': pn,
            'tri': tri,
            'trir': trir,
            'trirllrho': trirllrho,
            'xr': xr,
            'xu': xu,
            'xv': xv,
            'xpsi': xpsi,
            'X': X,
            'yr': yr,
            'yu': yu,
            'yv': yv,
            'ypsi': ypsi,
            'Y': Y,
            'lonr': lonr,
            'lonu': lonu,
            'lonv': lonv,
            'lonpsi': lonpsi,
            'latr': latr,
            'latu': latu,
            'latv': yv,
            'latpsi': latpsi,
            'h': h,
            'basemap': basemap
        }

    gridfile.close()

    return grid