ifpServer D2D netCDF File Format

October 6, 2002

This document describes the format of the netCDF file that is: If you are interested in the format of the netCDF files generated from the ifpnetCDF product formatter  or read by the iscMosaic program , then refer to the netCDF File Format Document.

Table of Contents
netCDF Required Dimensions
netCDF Variable Names
netCDF Variable Attributes
netCDF Global Attributes
Diagnosing Model Problems
Example of ncdump


netCDF Required Dimensions

Each netCDF file is required to contain the following set of dimensions:
 
Dimension Description Required by GFESuite?
x X-dimension of all grids Yes
y Y-dimension of all grids Yes



 

netCDF Variable Names

Each netCDF variable name represents a set of grids, plus additional information:
 
 
Variable Name Format
Example Data Type Dimensions Description Required by GFESuite?
name gh 4-D cube of data, float (#grids, #levels, y,x) The actual gridded data is contained in these variables. Attributes are associated with this variable. Yes
nameLevels ghLevels 2-D array of charaters (#levels, charsPerLevel) The names of each of the vertical levels is in this variable, such as 500MB. Yes, if there are more than 1 level in the data. If not specified, then the level name is assigned "Dflt".
nameInventory ghInventory 2-D array of characters (#grids, #levels) An indicator 0 or 1 is used to denote whether that grid is present in the "name" variable. These bits change as model data arrives. Yes
_tp12, _tp6 _tp12, _tp6 array of numbers, int #grids Indicates whether total precipitation is for a 6 hour period or for a 12 hour period.  Some models provide QPF grids every 6 hours, but the durations of each grid alternates between QPF for the last 6 hours, and the last 12 hours. No.  If not specified, then it assumed that Total Precipitation (_tp) valid accumulation time is the time between grids.
valtimeMINUSreftime valtimeMINUSreftime array of numbers, int # grids indicates the offset in seconds between the model reference (base) time, and the grid. Yes
reftime reftime single number, float n/a indicates the number of seconds between Jan 1, 1970 at 0000z and the model base time (analysis time) No. The D2D convention is to use the file name as the base model time. The "reftime" variable is not used.
model model array of characters namelen defines the model name as it appears in the GFE GUI and ifpServer databases.  There can be only ONE netCDF file valid for the same time that has the same model definition, or the ifpServer/GFE will not see all of them. Yes. The model specified will be modified by eliminating spaces and non-alphanumeric characters. Note that the model name may be overridden using the D2DDIRS in serverConfig.py and localConfig.py. Thus if the "model" variable in the netCDF file isn't to your liking or there is a conflict with other netCDF files, you can effectively change it using the syntax in the D2DDIRS definition.
staticTopo staticTopo 2-D grid, float (y, x) Contains the topography in meters for the model.  No. This field is recommended, but not required.

netCDF variable Attributes

Every "name" variable in the netCDF file has a collection of attributes.  In the table below, we briefly describe each attribute and its meaning.  For more information about a particular attribute, click on the link.
 
 
Attribute Name Attribute Description Required by GFESuite?
long_name Contains a descriptive name that describes the variable. No. If long_name is not specified, GFESuite will use the variable name instead.
units Units for the variable.  This is used by the GFE to display units in the legend, ifpIMAGE for the units in its legend, and for copy/paste operations within the GFE to determine how to convert units to the Fcst database units. Yes.
valid_range Minimum and maximum range of the variable.  This is used by the ifpServer to limit the data, and by the GFE to assign color tables to the data. (ifpServer also looks for valid_min and valid_max if valid_range does not exist) No. If not specified, then the minimum is assigned as 0 and the maximum assigned as 5000.
_FillValue Fill Value, indicating no data at the point. No.  If not specified, then the fill value is assumed to be MAXFLOAT.

netCDF Global Attributes

 
The following netCDF global attributes are required in order for the ifpServer to recognize the netCDF file as valid:
 
Attribute Description Required by GFESuite?
projName Contains the projection name.  Must be one of the following: LAMBERT_CONFORMAL, MERCATOR, STEREOGRAPHIC, LATLON, CYLINDRICAL_EQUIDISTANT Yes
lon00 Longitude in degrees of lower-left grid point (0, 0) Yes
lat00 Latitude in degrees of lower-left grid point (0, 0) Yes
latNxNy Latitude in degrees of upper-right grid point (maxX, maxY) Yes
lonNxNy Longitude in degrees of upper-right grid point (maxX, maxY) Yes
centralLon Center longitude for the mercator projection, where the mercator projection is parallel to the Earth's surface. Center longitude for the polar stereographic and Lambert Conformal projections, where the projection has north as straight up. Yes
centralLat Center latitude for the polar stereographic and Lambert Conformal projections, where the plane intersects the Earth's surface. Yes


 

Diagnosing Model Problems

If you point the ifpServer to a D2D directory and the model is not appearing, verify that: If all else fails, you can turn on the debugging logging option in the ifpServer.  In this mode the ifpServer will log all problems it finds with model data files.  To turn on this feature, perform the following steps:
  1. Edit the file release/etc/BASE/logPref/ifpServer.logPref, where release is the installation directory. On AWIPS-baseline equipment this file is located at /awips/GFESuite/primary/etc/BASE/logPref/ifpServer.logPref.  Add the following line in the middle of the file (before the prefix section).  Refer to the log files document for details. Add an entry:     all  D2DFile.C  file debug = on
  2. Stop and restart the ifpServer.
  3. Look in the server log files.  It will show the problems for all files it finds.  If it doesn't identify your file or directory, recheck your D2DDIRS to be sure you have set it up correctly.



Example of ncdump

Header dump of netcdf file
Valid Time dump
model dump
inventory dump
levels dump
This is an example of an ncdump -h of an NAM model, showing all of the correct fields:

ncdump -h 20020327_1200

netcdf 20020327_1200 {
dimensions:
    record = UNLIMITED ; // (11 currently)
    n_valtimes = 15 ;
    data_variables = 20 ;
    charsPerLevel = 10 ;
    namelen = 132 ;
    x = 93 ;
    y = 65 ;
    levels_1 = 1 ;
    levels_2 = 2 ;
    levels_5 = 5 ;
    levels_19 = 19 ;
    levels_25 = 25 ;
variables:
    float gh(record, levels_19, y, x) ;
        gh:long_name = "Geopotential height" ;
        gh:units = "m" ;
        gh:udunits = "meters" ;
        gh:uiname = "geoPotHt" ;
        gh:valid_range = 0.f, 20000.f ;
        gh:_FillValue = -99999.f ;
        gh:_n3D = 19 ;
        gh:levels = "MB 1000-100 by 50" ;
    char ghLevels(levels_19, charsPerLevel) ;
    char ghInventory(n_valtimes, levels_19) ;
    float rh(record, levels_25, y, x) ;
        rh:long_name = "Relative Humidity" ;
        rh:units = "%" ;
        rh:udunits = "percent" ;
        rh:uiname = "rh" ;
        rh:valid_range = 0.f, 100.f ;
        rh:_FillValue = -99999.f ;
        rh:_n3D = 20 ;
        rh:levels = "FHAG 2  MB 1000-100 by 50  BL 0>30 30>60 60>90 90>120 120>150" ;
    char rhLevels(levels_25, charsPerLevel) ;
    char rhInventory(n_valtimes, levels_25) ;
    float t(record, levels_25, y, x) ;
        t:long_name = "Temperature" ;
        t:units = "K" ;
        t:udunits = "degree_Kelvin" ;
        t:uiname = "T" ;
        t:valid_range = 180.f, 330.f ;
        t:_FillValue = -99999.f ;
        t:_n3D = 20 ;
        t:levels = "FHAG 2  MB 1000-100 by 50  BL 0>30 30>60 60>90 90>120 120>150" ;
    char tLevels(levels_25, charsPerLevel) ;
    char tInventory(n_valtimes, levels_25) ;
    float uw(record, levels_25, y, x) ;
        uw:long_name = "u wind component" ;
        uw:units = "m/s" ;
        uw:udunits = "meter/sec" ;
        uw:uiname = "uWind" ;
        uw:valid_range = -150.f, 150.f ;
        uw:_FillValue = -99999.f ;
        uw:_n3D = 20 ;
        uw:levels = "FHAG 10 MB 1000-100 by 50  BL 0>30 30>60 60>90 90>120 120>150" ;
    char uwLevels(levels_25, charsPerLevel) ;
    char uwInventory(n_valtimes, levels_25) ;
    float vw(record, levels_25, y, x) ;
        vw:long_name = "v wind component" ;
        vw:units = "m/s" ;
        vw:udunits = "meter/sec" ;
        vw:uiname = "vWind" ;
        vw:valid_range = -150.f, 150.f ;
        vw:_FillValue = -99999.f ;
        vw:_n3D = 20 ;
        vw:levels = "FHAG 10 MB 1000-100 by 50  BL 0>30 30>60 60>90 90>120 120>150" ;
    char vwInventory(n_valtimes, levels_25) ;
    float av(record, levels_5, y, x) ;
        av:long_name = "absolute vorticity" ;
        av:units = "1/s" ;
        av:udunits = "1/second" ;
        av:uiname = "absVort" ;
        av:valid_range = -0.01f, 0.01f ;
        av:_FillValue = -99999.f ;
        av:_n3D = 4 ;
        av:levels = "MB 1000 850 700 500 250" ;
    char avLevels(levels_5, charsPerLevel) ;
    char avInventory(n_valtimes, levels_5) ;
    float pvv(record, levels_19, y, x) ;
        pvv:long_name = "Pressure vertical velocity" ;
        pvv:units = "Pa/s" ;
        pvv:udunits = "pascal/second" ;
        pvv:uiname = "Pvv" ;
        pvv:valid_range = -2.5f, 2.5f ;
        pvv:_FillValue = -99999.f ;
        pvv:_n3D = 19 ;
        pvv:levels = "MB 1000-100 by 50" ;
    char pvvLevels(levels_19, charsPerLevel) ;
    char pvvInventory(n_valtimes, levels_19) ;
    float p(record, levels_1, y, x) ;
        p:long_name = "pressure" ;
        p:units = "Pa" ;
        p:udunits = "pascal" ;
        p:uiname = "atmP" ;
        p:valid_range = 0.f, 110000.f ;
        p:_FillValue = -99999.f ;
        p:_n3D = 1 ;
        p:levels = "SFC" ;
    char pLevels(levels_1, charsPerLevel) ;
    char pInventory(n_valtimes, levels_1) ;
    float heli(record, levels_1, y, x) ;
        heli:long_name = "helicity" ;
        heli:units = "m/s2" ;
        heli:udunits = "meter/second2" ;
        heli:uiname = "hel" ;
        heli:valid_range = 0.f, 1000.f ;
        heli:_FillValue = -99999.f ;
        heli:_n3D = 0 ;
        heli:levels = "FHAG 0>30" ;
    char heliLevels(levels_1, charsPerLevel) ;
    char heliInventory(n_valtimes, levels_1) ;
    float cape(record, levels_2, y, x) ;
        cape:long_name = "Convective Available Potential Energy" ;
        cape:units = "J/kg" ;
        cape:udunits = "joule/Kilogram" ;
        cape:uiname = "CAPE" ;
        cape:valid_range = 0.f, 6000.f ;
        cape:_FillValue = -99999.f ;
        cape:_n3D = 0 ;
        cape:levels = "SFC BL 0>180" ;
    char capeLevels(levels_2, charsPerLevel) ;
    char capeInventory(n_valtimes, levels_2) ;
    float cin(record, levels_2, y, x) ;
        cin:long_name = "Convective Inhibition" ;
        cin:units = "J/kg" ;
        cin:udunits = "joule/Kilogram" ;
        cin:uiname = "convInhib" ;
        cin:valid_range = 0.f, 400.f ;
        cin:_FillValue = -99999.f ;
        cin:_n3D = 0 ;
        cin:levels = "SFC BL 0>180" ;
    char cinLevels(levels_2, charsPerLevel) ;
    char cinInventory(n_valtimes, levels_2) ;
    float bli(record, levels_1, y, x) ;
        bli:long_name = "Best lifted index" ;
        bli:units = "K" ;
        bli:udunits = "degree_Kelvin" ;
        bli:uiname = "bestLftInd" ;
        bli:valid_range = -20.f, 50.f ;
        bli:_FillValue = -99999.f ;
        bli:_n3D = 0 ;
        bli:levels = "BL 0>180" ;
    char bliLevels(levels_1, charsPerLevel) ;
    char bliInventory(n_valtimes, levels_1) ;
    float pli(record, levels_1, y, x) ;
        pli:long_name = "Parcel lifted index" ;
        pli:units = "K" ;
        pli:udunits = "degree_Kelvin" ;
        pli:uiname = "parcLftInd" ;
        pli:valid_range = -20.f, 50.f ;
        pli:_FillValue = -99999.f ;
        pli:_n3D = 0 ;
        pli:levels = "BL 0>30" ;
    char pliLevels(levels_1, charsPerLevel) ;
    char pliInventory(n_valtimes, levels_1) ;
    float pw(record, levels_1, y, x) ;
        pw:long_name = "precipitable water" ;
        pw:units = "mm" ;
        pw:udunits = "millimeter" ;
        pw:uiname = "precipH2O" ;
        pw:valid_range = 0.f, 300.f ;
        pw:_FillValue = -99999.f ;
        pw:_n3D = 0 ;
        pw:levels = "EA" ;
    char pwLevels(levels_1, charsPerLevel) ;
    char pwInventory(n_valtimes, levels_1) ;
    float emsp(record, levels_1, y, x) ;
        emsp:long_name = "ETA Mean Sea Level Pressure" ;
        emsp:units = "Pa" ;
        emsp:udunits = "pascal" ;
        emsp:uiname = "ETAMSL" ;
        emsp:valid_range = 80000.f, 110000.f ;
        emsp:_FillValue = -99999.f ;
        emsp:_n3D = 0 ;
        emsp:levels = "MSL" ;
    char emspLevels(levels_1, charsPerLevel) ;
    char emspInventory(n_valtimes, levels_1) ;
    float pmsl(record, levels_1, y, x) ;
        pmsl:long_name = "pressure at mean sea level" ;
        pmsl:units = "Pa" ;
        pmsl:udunits = "pascal" ;
        pmsl:uiname = "PMSL" ;
        pmsl:valid_range = 80000.f, 110000.f ;
        pmsl:_FillValue = -99999.f ;
        pmsl:_n3D = 0 ;
        pmsl:levels = "MSL" ;
    char pmslLevels(levels_1, charsPerLevel) ;
    char pmslInventory(n_valtimes, levels_1) ;
    float cp(record, levels_1, y, x) ;
        cp:long_name = "convective precipitation" ;
        cp:units = "mm" ;
        cp:udunits = "millimeter" ;
        cp:uiname = "convPrecip" ;
        cp:valid_range = 0.f, 1000.f ;
        cp:_FillValue = -99999.f ;
        cp:_n3D = 0 ;
        cp:levels = "SFC" ;
    char cpLevels(levels_1, charsPerLevel) ;
    char cpInventory(n_valtimes, levels_1) ;
    float tp(record, levels_1, y, x) ;
        tp:long_name = "total precipitation" ;
        tp:units = "mm" ;
        tp:udunits = "millimeter" ;
        tp:uiname = "totPrecip" ;
        tp:valid_range = 0.f, 1000.f ;
        tp:_FillValue = -99999.f ;
        tp:_n3D = 0 ;
        tp:levels = "SFC" ;
    char tpLevels(levels_1, charsPerLevel) ;
    char tpInventory(n_valtimes, levels_1) ;
    float _tp12(n_valtimes) ;
    float _tp6(n_valtimes) ;
    int valtimeMINUSreftime(n_valtimes) ;
        valtimeMINUSreftime:units = "seconds" ;
    double reftime ;
        reftime:long_name = "reference time" ;
        reftime:units = "seconds since (1970-1-1 00:00:00.0)" ;
    char origin(namelen) ;
    char model(namelen) ;
    float staticTopo(y, x) ;
        staticTopo:units = "meters" ;
        staticTopo:long_name = "Topography" ;
        staticTopo:_FillValue = -99999.f ;
    float staticCoriolis(y, x) ;
        staticCoriolis:units = "/second" ;
        staticCoriolis:long_name = "Coriolis parameter" ;
        staticCoriolis:_FillValue = -99999.f ;
    float staticSpacing(y, x) ;
        staticSpacing:units = "meters" ;
        staticSpacing:long_name = "Grid spacing" ;
        staticSpacing:_FillValue = -99999.f ;

// global attributes:
        :cdlDate = "20010328" ;
        :depictorName = "grid211@16944264" ;
        :projIndex = 3 ;
        :projName = "LAMBERT_CONFORMAL" ;
        :centralLat = 25.f ;
        :centralLon = -95.f ;
        :rotation = 25.f ;
        :xMin = -0.255644f ;
        :xMax = 0.196647f ;
        :yMax = -0.562235f ;
        :yMin = -0.876877f ;
        :lat00 = 12.19004f ;
        :lon00 = -133.459f ;
        :latNxNy = 57.28995f ;
        :lonNxNy = -49.38491f ;
        :dxKm = 78.04174f ;
        :dyKm = 78.04293f ;
        :latDxDy = 40.60606f ;
        :lonDxDy = -100.5548f ;

Looking at specifics for the valtimeMINUSreftime:

ncdump -v valtimeMINUSreftime 20020327_1200

data:

 valtimeMINUSreftime = 0, 21600, 43200, 64800, 86400, 108000, 129600, 151200,
    172800, 194400, 216000, 237600, 259200, 280800, 302400 ;
 

Looking at specifics for the model:

ncdump -v model 20020327_1200

data:

 model = "ETA" ;

Looking at specifics for the inventory bits:

ncdump -v ghInventory 20020327_1200

data:

 ghInventory =
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "1111111111111111111",
  "",
  "",
  "",
  "" ;
 

Looking at the specifics for the levels:

ncdump -v ghLevels 20020327_1200

data:

 ghLevels =
  "MB 1000   ",
  "MB 950    ",
  "MB 900    ",
  "MB 850    ",
  "MB 800    ",
  "MB 750    ",
  "MB 700    ",
  "MB 650    ",
  "MB 600    ",
  "MB 550    ",
  "MB 500    ",
  "MB 450    ",
  "MB 400    ",
  "MB 350    ",
  "MB 300    ",
  "MB 250    ",
  "MB 200    ",
  "MB 150    ",
  "MB 100    " ;