|
|
|||
|
||||
John Caron
last updated Dec 15, 2004
The NetCDF-Java 2.2 library decodes the NEXRAD level 2 and level 3 radar data, and represents it in the netCDF-3 data model, and optionally writes it to a netCDF file. This document represents our current thinking on how to best represent radar scan data in netCDF, hopefully useful to any radar data.
The raw files are typically a collection of radial data records, a single beam at a specfied azimuth, elevation, and time. We would like to collect adjacent radials into a scan, and possibly multiple scans into a volume.
The main idea is to associate variables containing coordinate information to the data variables, for example:
float Reflectivity(scanR, radial, gateR);
:units = "db";
:long_name = "Reflectivity in dbZ";
:missing_value = NaN; // float
:_CoordinateAxes = "timeR elevationR azimuthR gateR";
int timeR(scanR, radial);
:long_name = "time since base date";
:units = "msecs since 2000-06-10T00:00:00Z";
float elevationR(scanR, radial);
:units = "degrees";
:long_name = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular";
float azimuthR(scanR, radial);
:units = "degrees";
:long_name = "azimuth angle in degrees: 0 = true north, 90 = east";
float gateR(gateR);
:units = "m";
:long_name = "radial distance to start of gate";
In this example the _CoordinateAxes attribute on the data variable Reflectivity associates the timeR, elevationR, azimuthR, and gateR variables as coordinates for the Reflectivity data. The gateR variable is a coordinate variable, but the others are not, so we call them coordinate axes to keep things clear. This usage of the _CoordinateAxes attribute follows a proposed attribute convention for coordinate systems.
The meaning of these coordinate axes is that the data at Reflectivity(i, j, k) has coordinates timeR(i, j), elevationR( i, j), azimuthR(i, j), and gateR(k). This, along with the lat, lon and elevation of the radar, is sufficient to locate each radar data value in spacce and time.
This example indicates that the elevation of each radial can vary. If in fact the elevation was constant for each scan, one could instead use
float elevationR(scanR); :units = "degrees"; :long_name = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular";
Another issue is that the validity of the data along the radial distance varies depending on elevation angle. What this really means is that the number of gates (the outer dimension) should vary. Since that doesnt fit the netCDF data model of rectangular arrays, we have chosen to simple return missing data values when the data becomes invalid. Another way to indicate this might be to add a variable, say:
int validNumberOfGates(scanR, radial);
:long_name = "number of gates before data becomes invalid";
netcdf C:/data/radar/level2/6500KHGX20000610_000110.raw {
dimensions:
radial = 367;
scanR = 14;
gateR = 460;
scanV = 14;
gateV = 920;
variables:
float Reflectivity(scanR, radial, gateR);
:units = "db";
:long_name = "Reflectivity in dbZ";
:missing_value = NaN; // float
:_CoordinateAxes = "timeR elevationR azimuthR distanceR";
int timeR(scanR, radial);
:long_name = "time since base date";
:units = "msecs since 2000-06-10T00:00:00Z";
float elevationR(scanR, radial);
:units = "degrees";
:long_name = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular";
float azimuthR(scanR, radial);
:units = "degrees";
:long_name = "azimuth angle in degrees: 0 = true north, 90 = east";
float distanceR(gateR);
:units = "m";
:long_name = "radial distance to start of gate";
float Velocity(scanV, radial, gateV);
:units = "m/s";
:long_name = "Dopplar Velocity";
:missing_value = NaN; // float
:_CoordinateAxes = "timeV elevationV azimuthV distanceV";
int timeV(scanV, radial);
:long_name = "time since base date";
:units = "msecs since 2000-06-10T00:00:00Z";
float elevationV(scanV, radial);
:units = "degrees";
:long_name = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular";
float azimuthV(scanV, radial);
:units = "degrees";
:long_name = "azimuth angle in degrees: 0 = true north, 90 = east";
float distanceV(gateV);
:units = "m";
:long_name = "radial distance to start of gate";
float SpectrumWidth(scanV, radial, gateV);
:units = "m/s";
:long_name = "Dopplar Spectrum Width";
:missing_value = NaN; // float
:_CoordinateAxes = "timeV elevationV azimuthV distanceV";
:format = "ARCHIVE2"; :base_date = "2000-06-10"; :start_datetime = "2000-06-10T00:01:10Z"; :end_datetime = "2000-06-10T00:06:02Z"; :VolumeCoveragePatternName = "16 elevation scans every 5 mins"; :VolumeCoveragePattern = 11; // int :Processing = "direct read of Nexrad Level 2 file into NetCDF-Java 2.2 API"; :DataType = "RADAR"; :Title = "Nexrad Level 2 Station null from 2000-06-10T00:01:10Z to 2000-06-10T00:06:02Z"; }
In this example, the reflectivity on the one hand, and the Velocity and SpectrumWidth on the other, have different gate sizes, so they need different gate dimensions and coordinates.
We keep the radials time-ordered, which means that the elevation and azimuth coordinates vary by radial and scan.
comments to John Caron
| Contact Us Site Map Search Terms and Conditions Privacy Policy Participation Policy | ||||||
|
||||||