Re: [netcdfgroup] What attributes/dimensions are required to be set on a variable to make it georeferenced?

  • To: Dave Allured - NOAA Affiliate <dave.allured@xxxxxxxx>
  • Subject: Re: [netcdfgroup] What attributes/dimensions are required to be set on a variable to make it georeferenced?
  • From: James Adams <monocongo@xxxxxxxxx>
  • Date: Mon, 30 Mar 2015 11:49:04 -0400
Thanks for all of this information, Dave. Sorry I was unclear about what my
real issue was -- it's not that I want to see the data set in any certain
way within Panoply, it's just that with other NetCDF files I've been using
the variables are denoted as Geo2D type when displayed in Panoply, and the
variable I had written via my Python code did not, and I thought that that
might tell us something.  However the main issue I was dealing with was
that I was unable to open the variable as a GeoGrid within my own Java
code. I've fixed that now by adding various attributes to the data set and
the variable, although it's not exactly clear which of these have made the
difference since I added them all at once. What's interesting is that I did
not add several of the attributes you mentioned below (for example no units
attribute for the lon and lat variables), but I am now able to see the
variable as a GeoGrid when I access it within my Java programs.  So perhaps
the question is less about how to get a georeferenced variable than it is
about what is required to be present on a variable in order to see/fetch it
as a GeoGrid via the NetCDF Java API, as these appear to be separate
concerns.

In any event below is the updated Python code I now use to create this
NetCDF file and the variable is now visible as a GeoGrid when I access it
within Java code using the NetCDF API. I will improve this further by
incorporating your suggestions below and those in the CF docs in order to
beef up the CF compliance, follow best practices, etc.

Thanks again for your help!

--James

------------------------------------------
Updated Python code for creating the NetCDF:

    # open the output file for writing, set its dimensions and variables
    output_dataset = netCDF4.Dataset(output_file, 'w')
    output_dataset.createDimension('time', None)
    output_dataset.createDimension('lon', len(input_lon_dimension))
    output_dataset.createDimension('lat', len(input_lat_dimension))

    # set some global group attributes
    output_dataset.title = 'nClimGrid soil constants, CONUS 5-km'
    output_dataset.source = 'conversion from data set provided by M.
Brewer/NIDIS'
    output_dataset.institution = 'National Climatic Data Center, NESDIS,
NOAA, U.S. Department of Commerce'
    output_dataset.standard_name_vocabulary = 'CF Standard Name Table (v26,
08 November 2013)'
    output_dataset.date_created = str(datetime.now())
    output_dataset.date_modified = str(datetime.now())

    # create lon dimension variable
    output_lon_variable = output_dataset.createVariable('lon','f4',('lon',))
    if 'units' in input_lon_variable.ncattrs():
        output_lon_variable.units = input_lon_variable.units
    output_lon_variable[0:len(input_lon_dimension):1] =
input_lon_variable[0:len(input_lon_dimension):1]
    output_lon_variable.long_name = 'longitude'
    output_lon_variable.standard_name = 'longitude'

    # create lat dimension variable
    output_lat_variable = output_dataset.createVariable('lat','f4',('lat',))
    if 'units' in input_lat_variable.ncattrs():
        output_lat_variable.units = input_lat_variable.units
    output_lat_variable[0:len(input_lat_dimension):1] =
input_lat_variable[0:len(input_lat_dimension):1]
    output_lat_variable.long_name = 'latitude'
    output_lat_variable.standard_name = 'latitude'

    # create a time variable with a single value
    output_time_variable =
output_dataset.createVariable('time','i4',('time',))
    output_time_variable.units = 'days since 1900-01-01 00:00:00'
    output_time_variable[0:1:1] = numpy.array([0])
    output_time_variable.long_name = 'time'
    output_time_variable.standard_name = 'time'
    output_time_variable.calendar = 'gregorian'

    # create the soil constant variable
    output_soil_variable =
output_dataset.createVariable('available_water_capacity','f4',('time',
'lon', 'lat'),

 fill_value=fill_value,
                                                         zlib=True,

 least_significant_digit=3)

    attributeDictionary = { "Conventions":"CF-1.3" }
    output_dataset.setncatts(attributeDictionary)

-------------------------------------------------------------
File header info shown by Panoply:

       Dataset type: Hierarchical Data Format, version 5

________________________________

netcdf file:/C:/tmp/nclimgrid/nclimgrid_soil.nc {
  dimensions:
    lon = 1385;
    time = UNLIMITED;   // (1 currently
    lat = 596;
  variables:
    float lon(lon=1385);
      :long_name = "longitude";
      :standard_name = "longitude";

    int time(time=1);
      :units = "days since 1900-01-01 00:00:00";
      :long_name = "time";
      :standard_name = "time";
      :calendar = "gregorian";
      :_ChunkSize = 1; // int

    float lat(lat=596);
      :long_name = "latitude";
      :standard_name = "latitude";

    float available_water_capacity(time=1, lon=1385, lat=596);
      :_FillValue = -999.9f; // float
      :least_significant_digit = 3; // int
      :_ChunkSize = 1, 1385, 596; // int

  // global attributes:
  :title = "nClimGrid soil constants, CONUS 5-km";
  :source = "conversion from data set provided by M. Brewer/NIDIS";
  :institution = "National Climatic Data Center, NESDIS, NOAA, U.S.
Department of Commerce";
  :standard_name_vocabulary = "CF Standard Name Table (v26, 08 November
2013)";
  :date_created = "2015-03-27 13:38:17.840000";
  :date_modified = "2015-03-27 13:38:17.840000";
  :Conventions = "CF-1.3";
  :geospatial_lon_min = "-100.02";
  :geospatial_lat_min = "24.563";
  :geospatial_lon_max = "-99.981";
  :geospatial_lat_max = "49.397";
}

On Fri, Mar 27, 2015 at 7:52 PM, Dave Allured - NOAA Affiliate <
dave.allured@xxxxxxxx> wrote:

> James,
>
> Here are the minimal georeferencing requirements for common climate
> software:
>
> * The NetCDF file must contain separate 1-dimensional latitude and
> longitude coordinate variables, in addition to the data variables.
>
> * Names of coordinate variables must be the same as their dimension names,
> for example lat(lat).
>
> * Coordinate variables and data variables must share the same dimension
> names for corresponding dimensions.  For example, water(time, lon, lat)
> would require lon(lon) and lat(lat).  This is the ONLY georef. requirement
> on the data variable itself.
>
> * Lat and lon coordinate variables must have corresponding "units"
> attributes of "degrees_north" and "degrees_east".  There are several
> acceptable alternate values, see CF conventions.
>
> * The units attribute must be type character, not type string, for
> compatibility with much older software and versions still in use.
>
> It is helpful to emulate real examples.  Check out these, starting with
> smaller CDL files near the top:
> http://www.unidata.ucar.edu/software/netcdf/examples/files.html
>
> Different softwares have different requirements.  The various conventions
> do not make perfect compatibility.  GIS and OSGeo requirements are more
> detailed.  Your real question may be more specific, "Why doesn't my file
> show up as Geo2D type in Panoply", in which case you should try a Panoply
> support forum.  HTH.
>
> --Dave A.
> NOAA/PSD/CIRES
>
>
> On Fri, Mar 27, 2015 at 9:33 AM, James Adams <monocongo@xxxxxxxxx> wrote:
>
>> I have a variable that I've created in a file which I want to be able to
>> read as a georeferenced data set, i.e. using something like this with the
>> Java API:
>>
>>         GridDataset gridDataset = GridDataset.open(netcdfFile);
>>         GeoGrid geoGrid = gridDataset.findGridByShortName(variableName);
>>
>> Currently the NetCDF variable looks like this (from ncdump):
>>
>> float available_water_capacity(time=1, lon=1385, lat=596);
>>   :_FillValue = -999.9f; // float
>>   :least_significant_digit = 3; // int
>>   :_ChunkSize = 1, 1385, 596; // int
>>
>> I assume that I have not set either sufficient attributes and/or
>> dimensions on the data variable (available_water_capacity), so I'm fishing
>> for ideas as to how I can flesh this out when creating/writing the files in
>> my Python code.  The NetCDF file is currently created like so:
>>
>>     # open the output file for writing, set its dimensions and variables
>>     output_dataset = netCDF4.Dataset(output_file, 'w')
>>     output_dataset.createDimension('time', None)
>>     output_dataset.createDimension('lon', len(input_lon_dimension))
>>     output_dataset.createDimension('lat', len(input_lat_dimension))
>>
>>     # create lon dimension variable
>>     output_lon_variable =
>> output_dataset.createVariable('lon','f4',('lon',))
>>     if 'units' in input_lon_variable.ncattrs():
>>         output_lon_variable.units = input_lon_variable.units
>>     output_lon_variable[0:len(input_lon_dimension):1] =
>> input_lon_variable[0:len(input_lon_dimension):1]
>>
>>     # create lat dimension variable
>>     output_lat_variable =
>> output_dataset.createVariable('lat','f4',('lat',))
>>     if 'units' in input_lat_variable.ncattrs():
>>         output_lat_variable.units = input_lat_variable.units
>>     output_lat_variable[0:len(input_lat_dimension):1] =
>> input_lat_variable[0:len(input_lat_dimension):1]
>>
>>     # create a time variable with a single value
>>     output_time_variable =
>> output_dataset.createVariable('time','i4',('time',))
>>     output_time_variable.units = 'days since 1900-01-01 00:00:00'
>>     output_time_variable[0:1:1] = numpy.array([0])
>>
>>     # create the soil constant variable
>>     output_soil_variable =
>> output_dataset.createVariable('available_water_capacity','f4',('time',
>> 'lon', 'lat'),
>>
>>  fill_value=fill_value,
>>                                                          zlib=True,
>>
>>  least_significant_digit=3)
>>
>>     attributeDictionary = { "Conventions":"CF-1.3" }
>>     output_dataset.setncatts(attributeDictionary)
>>
>>
>> The trouble is that when I read this NetCDF file in Java code which uses
>> the approach outlined above it does not find the variable as a grid in the
>> GridDataset, however I'm using this approach with other NetCDF variables
>> which are correctly georeferenced (they show up as Geo2D types in Panoply),
>> so I assume that I've failed to completely flesh out this variable so that
>> it'll be recognized as a grid. What more might I add in order to make this
>> variable discoverable as a georeferenced grid?
>>
>> Thanks in advance if anyone has suggestions on this.
>>
>> --James
>>
>
>
  • 2015 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the netcdfgroup archives: