简体   繁体   中英

How to write variable attributes in NetCDF file using python

I am trying to write a Numpy array to a netcdf file which will ultimately be read into ArcGIS 10.2 as a raster file with time dimension. When ArcGIS reads in my current file it is not setting the man, min, and missing values properly so I am assuming I need to set theses when I create my NetCDF file. However, I am having trouble figureing out how to set these variable attributes when creating the file. Here is my current code.

import numpy as n
from scipy.io import netcdf

def gis_netcdf(data,arr,filename):
  f=netcdf.netcdf_file(outfile+filename,'w')
  f.history='Downscaled CMIP5 data which has been averaged over all'\
    'models and decadaly averaged'

  f.createDimension('time',9)
  f.createDimension('lat',len(data['lat']))
  f.createDimension('lon',len(data['lon']))

  time=f.createVariable('time',int,('time',))
  lat=f.createVariable('lat',float,('lat',))
  lon=f.createVariable('lon',float,('lon',))
  fog=f.createVariable('fog',float,('time','lat','lon',))

  #attributes I need set:
  #  'missing_value':1e20
  #  'valid_min':n.min(arr[arr<500])
  #  'valid_max':n.max(arr[arr<500])

  time[:]=n.arange(2010,2091,10)
  time.units='decades since 1950' 

  lat[:]=data['lat']
  lat.units='Degrees North'

  lon[:]=data['lon']
  lon.units='Degrees East'

  fog[:]=arr
  fog.units='Change in Hours'

  f.close

*****Attempt at Solution which was posted**********

I added the following lines to my above code:

  fog.missing_value=1e20
  fog.valid_min=n.min(arr[arr<500])
  fog.valid_max=n.max(arr[arr<500])

and it did not work. This is my ncdump output

netcdf pixel_model_fog85 {
dimensions:
        time = 9 ;
        lat = 20 ;
        lon = 18 ;

variables:
        double lat(lat) ;
                lat:units = "Degrees North" ;
        double lon(lon) ;
                lon:units = "Degrees East" ;
        double fog(time, lat, lon) ;
                fog:units = "Change in Hours" ;
        long time(time) ;
                time:units = "decades since 1950" ;

// global attributes:
                :history = "Downscaled CMIP5 data which has been        averaged over all models and decadaly averaged" ;

data:

 lat = 36.3125, 36.4375, 36.5625, 36.6875, 36.8125, 36.9375, 37.0625,
    37.1875, 37.3125, 37.4375, 37.5625, 37.6875, 37.8125, 37.9375, 38.0625,
38.1875, 38.3125, 38.4375, 38.5625, 38.6875 ;

You just define them in a similar fashion as you've already done for the units attribute.

fog.missing_value = 1e20
fog.valid_min = [whatever value this should be]

-- EDIT --

Here is a full sample script that is working fine on my end. Note that I define all attributes in a single section before populating any data to the variables. I also use the data type shortcuts, like 'i' and 'f4', during the variable defining. While this works, I do recommend switching from the Scipy netCDF package to python-netCDF4 .

import numpy as np

from scipy.io.netcdf import netcdf_file

# Define some dummy data
time_arr = range(10)
lat_arr = np.array([30.5, 40., 40.5])
lon_arr = np.array([200., 203., 206.])
ntim, nlat, nlon = len(time_arr), len(lat_arr), len(lon_arr)

fog_arr = np.random.randn(ntim,nlat,nlon)

# Write out data to a new netCDF file with some attributes
filename = netcdf_file('./tmp_netcdf.nc', 'w')

# Dimensions
filename.createDimension('time', ntim)
filename.createDimension('lat', nlat)
filename.createDimension('lon', nlon)

# Variables
time = filename.createVariable('time', 'i', ('time',))
lat = filename.createVariable('lat', 'f4', ('lat',))
lon = filename.createVariable('lon', 'f4', ('lon',))
fog = filename.createVariable('fog', 'f4', ('time', 'lat', 'lon',))

# Attributes
time.units = 'decades since 1950'
lat.units = 'degrees north'
lon.units = 'degrees east'
fog.units = 'change in hours'
fog.missing_val = 1e20
fog.valid_min = np.min(fog_arr)

# Populate the variables with data
time[:] = time_arr
lat[:] = lat_arr
lon[:] = lon_arr
fog[:,:,:] = fog_arr[:,:,:]

filename.close()

Checking with ncdump:

>>> ncdump -h tmp_netcdf.nc
netcdf tmp_netcdf {
dimensions:
time = 10 ;
lat = 3 ;
lon = 3 ;
variables:
float fog(time, lat, lon) ;
    fog:units = "change in hours" ;
    fog:valid_min = -2.33124982071635 ;
    fog:missing_val = 1.e+20f ;
int time(time) ;
    time:units = "decades since 1950" ;
float lat(lat) ;
    lat:units = "degrees north" ;
float lon(lon) ;
    lon:units = "degrees east" ;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM