Example #1
0
def make_3D_NetCDF(ncfilename, wd, debug=False):
    """ Create NetCDF of 3D arrays for all variables in 2D NetCDF file
         Takes a table form NetCDF and build 3D arrays from lat and lon
         in the given file.  """

    # --- Read existing & setup new NetCDF file
    ncfile2D = Dataset(ncfilename, 'r', format='NETCDF4')

    # Setup dimensions
    vars = ncfile2D.variables
    if debug:
        print[i for i in vars]
    lats, lons, Epoch = [ncfile2D[i] for i in 'LAT', 'LON', 'Epoch']
    if debug:
        print[len(i) for i in lats, lons, Epoch]
    lats, lons, Epoch = [np.array(i) for i in lats, lons, Epoch]

    lats, lons = [list(sorted(set(i))) for i in lats, lons]
    # remove fill value. ( 9.969209968386869e+36 ) <= Improve this approach...
    [i.pop(-1) for i in lons, lats]

    # setup 3D NetCDF file
    ncfilename = ncfilename.split('.nc')[0]+'_3D.nc'
    ncfile = Dataset(ncfilename, 'w', format='NETCDF4')
    ncfile.createDimension('lat', len(lats))
    ncfile.createDimension('lon', len(lons))
    ncfile.createDimension('time', None)

    # Define the coordinate variables. They will hold the coordinate
    # information, that is, the latitudes and longitudes.
    time = ncfile.createVariable('time', 'f4', ('time',))
    lat = ncfile.createVariable('lat', 'f4', ('lat',))
    lon = ncfile.createVariable('lon', 'f4', ('lon',))

    # --- Add meta data
    # Assign units attributes to coordinate var data. This attaches a
    # text attribute to each of the coordinate variables, containing the
    # units.
    lat.units = 'degrees_north'
    lat.long_name = 'Latitude'
    lat.standard_name = 'Latitude'
    lat.axis = "Y"

    lon.units = 'degrees_east'
    lon.long_name = 'Longitude'
    lon.standard_name = 'Longitude'
    lon.axis = "X"

    time.units = 'seconds since 1970-01-01 00:00:00'
    time.calendar = "standard"
    time.standard_name = 'Time'
    time.axis = "T"

    # set global varibles
    ncfile.Description = 'planeflight output from '.format(wd)
    ncfile.Contact = 'Tomas Sherwen ([email protected])'
#    ncfile.History = 'Created {}'.format(  time.ctime(time.time()) )
    ncfile.Grid = 'lat: {}-{}, lon: {}-{}'.format(lats[0], lats[-1],
                                                  lons[0], lons[-1])
#    ncfile.Temp_Res = "Hourly"
#    ncfile.SpatialCoverage='Global'

    # write data to coordinate vars.
    lon[:] = lons
    lat[:] = lats

    # Get unique timesteps
    timesteps = sorted(set(Epoch))
    # masked 1st value ( headers? )
    timesteps.pop(0)

    # set time dimension to timestep values
    time[:] = timesteps

    # select only 3D vars
    vars3D = get_3D_vars(vars)

    # --- Loop 3D species and create variables (with set dimensions)
    for var in vars3D:
        ncfile.createVariable(var, var2type(var), ('time', 'lat', 'lon'), )

    # close NetCDF
    ncfile.close()

    # ---  Loop through timesteps (epoch) and add to NetCDF
    # Loop over timesteps
    for t in timesteps:

        # open NetCDF in append mode
        ncfile = Dataset(ncfilename, 'a', format='NETCDF4')

        # get 1st and last indices for time stamp
        start, end = [(i.min(), i.max())
                      for i in np.where(ncfile2D.variables['Epoch'] == t)][0]

        # Extract Data for timestep & species
        for var in vars3D:

            data_ = ncfile2D.variables[var][start:end]
            lons_ = ncfile2D.variables['LON'][start:end]
            lats_ = ncfile2D.variables['LAT'][start:end]
            if debug:
                print t, var, [i.shape for i in data_, lats_, lons_]

            # stack data by LAT/LON to 3D array ( using pandas )
            df = DataFrame(data_, index=[lats_, lons_]).unstack()

            # add data to array
            ncfile.variables[var][timesteps.index(t)] = df.values

            # remove from memory
            del df, data_, lats_, lons_

        # Save out final NetCDF file
        ncfile.close()