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()