<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<META NAME="Generator" CONTENT="MS Exchange Server version 6.0.6617.47">
<TITLE>Possible enhanced NetCDF support in GDAL.</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/rtf format -->

<P><FONT SIZE=2 FACE="Arial">Hello,</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">I've been using the gdal-1.2.6 distribtion as part of a MapServer build and have had need to access netCDF files. I found the netCDF driver too inflexible to read the files I needed to access and have customised the driver code to be more flexible. The implementation I have currently works very well and I'm happy to make it available for adapatation / inclusion into future releases of gdal. I don't know the correct protocol for this nor whether the gdal team are interested so I'm asking you now. What should I do. </FONT></P>

<P><FONT SIZE=2 FACE="Arial">To illustrate the changes I have made to the gdal netCDF driver and to possibly gain your interest in it I'll now attempt to describe it. The original driver assumes a particular netCDF file structure and variable names. For my modified driver I have chosen to explicitely specify how the driver should read the file in a generic fashion. I have achieved this by having a xml file that specifies which nc file and how to interpret it that you construct for every nc file that you wish to read. Then when the driver opens a file it accepts either the properly constructed xml file or the traditional nc file as a valid format. If an nc file then it interprets it in identical fashion to the original driver for backward compatibility. The xml file format required is as follows and is taken directly from a comment block within my modified code:</FONT></P>

<P><FONT SIZE=2 FACE="Arial">// This is a more advanced means of opening netCDF files that allows raster </FONT>

<BR><FONT SIZE=2 FACE="Arial">// information to be extracted from files whose data is not held in the </FONT>

<BR><FONT SIZE=2 FACE="Arial">// structure assumed by the original netCDF driver code. The XML file referenced </FONT>

<BR><FONT SIZE=2 FACE="Arial">// by poOpenInfo contains meta data instructing this driver on which cdf file to </FONT>

<BR><FONT SIZE=2 FACE="Arial">// open and how it should interpret the data within.</FONT>

<BR><FONT SIZE=2 FACE="Arial">// </FONT>

<BR><FONT SIZE=2 FACE="Arial">// XML file format for specification as follows:</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp; &lt;CDF&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;FileName&gt;{name}&lt;/FileName&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;DimNameLon&gt;{name}&lt;/DimNameLon&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;DimNameLat&gt;{name}&lt;/DimNameLat&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Variable&gt;{name}&lt;/Variable&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Units&gt;{name}&lt;/Units&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;NumberOfBands&gt;{value}&lt;/NumberOfBands&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;NoDataValue&gt;{value}&lt;/NoDataValue&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Extent&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Top&gt;{value}&lt;/Top&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Left&gt;{value}&lt;/Left&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Bottom&gt;{value}&lt;/Bottom&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Right&gt;{value}&lt;/Right&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;/Extent&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Range&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Minimum&gt;{value}&lt;/Minimum&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Maximum&gt;{value}&lt;/Maximum&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ColorTable&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;NumberOfEntries&gt;{value}&lt;/NumberOfEntries&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Scheme&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Hue&gt;{Start value} {End value}&lt;/Hue&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Lightness&gt;{Start value} {End value}&lt;/Lightness&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Saturation&gt;{Start value} {End value}&lt;/Saturation&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Scheme&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type&gt;{name}&lt;/Type&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Entry1&gt;{Value 1} {Value 2} {Value3} {Value4}&lt;Entry1&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Entry2&gt;{Value 1} {Value 2} {Value3} {Value4}&lt;Entry2&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Entry3&gt;{Value 1} {Value 2} {Value3} {Value4}&lt;Entry3&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;EntryX&gt;{Value 1} {Value 2} {Value3} {Value4}&lt;EntryX&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/ColorTable&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;/Range&gt; </FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Scaling&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Scale&gt;{value}&lt;/Scale&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Offset&gt;{value}&lt;/Offset&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;/Scaling&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Band1&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimName1}&gt;{value}&lt;/{ExtraDimName1}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimName2}&gt;{value}&lt;/{ExtraDimName2}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimNameM}&gt;{value}&lt;/{ExtraDimNameM}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;/Band1&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;Band2&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimName1}&gt;{value}&lt;/{ExtraDimName1}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimName2}&gt;{value}&lt;/{ExtraDimName2}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimNameM}&gt;{value}&lt;/{ExtraDimNameM}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;/Band2&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;BandN&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimName1}&gt;{value}&lt;/{ExtraDimName1}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimName2}&gt;{value}&lt;/{ExtraDimName2}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;{ExtraDimNameM}&gt;{value}&lt;/{ExtraDimNameM}&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp;&nbsp;&nbsp; &lt;/BandN&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//&nbsp; &lt;/CDF&gt;</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// FileName is the fully qualified name and path of the netCDF file you are</FONT>

<BR><FONT SIZE=2 FACE="Arial">// processing. DimNameLon and DimNameLat name the dimensions in the CDF variable</FONT>

<BR><FONT SIZE=2 FACE="Arial">// that correspond to longitudes and latitudes. If variable is a 2 dimension </FONT>

<BR><FONT SIZE=2 FACE="Arial">// array then NumberOfBands is implicitely 1. In such case NumberOfBands is </FONT>

<BR><FONT SIZE=2 FACE="Arial">// irrelevent and so too are the &lt;BandN&gt; sections. </FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// &lt;Extent&gt; is optional and specifies the co-ordinate extent of the data. If </FONT>

<BR><FONT SIZE=2 FACE="Arial">// specified this is used to create the mapping for this raster data. </FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// &lt;Range&gt; is optional and specifies the maximum and minimum data values in </FONT>

<BR><FONT SIZE=2 FACE="Arial">// variable to consider to be usable data. </FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// &lt;Scaling&gt; is optional and specifies the scale and offset parameters to </FONT>

<BR><FONT SIZE=2 FACE="Arial">// apply to the variable data using simple linear scaling. </FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// &lt;ColourTable&gt; is optional and if specified along with &lt;Range&gt; will result in</FONT>

<BR><FONT SIZE=2 FACE="Arial">// the driver colourising the image over the specified range using the specified</FONT>

<BR><FONT SIZE=2 FACE="Arial">// colour table. The colour entries are ordered from lowest to highest. The </FONT>

<BR><FONT SIZE=2 FACE="Arial">// number of values required in each colour entry depends on the &lt;Type&gt; which </FONT>

<BR><FONT SIZE=2 FACE="Arial">// may be one of Gray, RGB, CMYK or HLS. For Gray {Value1} is only required. For</FONT>

<BR><FONT SIZE=2 FACE="Arial">// RGB {Value1} is the red value, {Value2} is the green value, {Value3} is the blue </FONT>

<BR><FONT SIZE=2 FACE="Arial">// value and {Value4}, which is optional, is the alpha value (alpha blending?). </FONT>

<BR><FONT SIZE=2 FACE="Arial">// For CMYK {Value1} is the cyan value, {Value2} is the magenta value, {Value3} </FONT>

<BR><FONT SIZE=2 FACE="Arial">// is the yellow value and {Value4} is the black value. For HLS {Value1} is the </FONT>

<BR><FONT SIZE=2 FACE="Arial">// hue value, {Value2} is the lightness value and {Value3} is the saturation value.</FONT>

<BR><FONT SIZE=2 FACE="Arial">// The last index in the colour table is used to represent transparent by setting</FONT>

<BR><FONT SIZE=2 FACE="Arial">// the no data value to that index.&nbsp; </FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// If &lt;Scheme&gt; is defined then the colour table colour entries and &lt;type&gt; field</FONT>

<BR><FONT SIZE=2 FACE="Arial">// are ignored and the colour table entries synthesised according to the &lt;Scheme&gt;.</FONT>

<BR><FONT SIZE=2 FACE="Arial">// The HLS colour type is used and the colour table entries are generated by a </FONT>

<BR><FONT SIZE=2 FACE="Arial">// linear interpolation between the start and end HLS parameters. If only one </FONT>

<BR><FONT SIZE=2 FACE="Arial">// value is given then the component is assumed constant with that value.</FONT>

<BR><FONT SIZE=2 FACE="Arial">//</FONT>

<BR><FONT SIZE=2 FACE="Arial">// In the cases where the number of dimensions in Variable exceeds 2 you must </FONT>

<BR><FONT SIZE=2 FACE="Arial">// specify the number of bands explicitely. Furthermore, each band must have </FONT>

<BR><FONT SIZE=2 FACE="Arial">// a number of dimension definitions to specify the fixed dimension values to</FONT>

<BR><FONT SIZE=2 FACE="Arial">// use in accessing the Variable data. The entry names correspond to the </FONT>

<BR><FONT SIZE=2 FACE="Arial">// dimension names in Variable and the values user specified. For an N dimension </FONT>

<BR><FONT SIZE=2 FACE="Arial">// Variable you must have N-2 ExtraDimName entries whose names are unique and </FONT>

<BR><FONT SIZE=2 FACE="Arial">// not duplicated in DimNameLon and DimNameLat. </FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">Modifications to the code were only made in the netcdfdataset.cpp and gdalcolortable.cpp files and the changes are only ansi C/C&#43&#43 without reliance on other libraries. The changes I made to gdalcolortable.cpp were ones to implement the HLS and CMYK colour models which had skeletons but no implementations. </FONT></P>

<P><FONT SIZE=2 FACE="Arial">Our typical application of this enhanced driver is to access and map oceanographic data such as SST contained in annual or six monthly aggregate files. These files typically have the data stored in 3d arrays (lat, lon, time) and sometimes 4d arrays (lat, lon, time, depth). With this modified driver it is simple to access a particular time slice for viewing as map data. The ability to colourise the data with a customisable colour table is a nice bonus. </FONT></P>

<P><FONT SIZE=2 FACE="Arial">If you are interested in including it or a modified version of it into new releases of gdal I'll gladly offer the code to you and bring it up to date to the latest development version, though I can't promise much commitment for furture maintenance. It would seem that this approach to generalisation would possbily work well with other file formats such as HDF.</FONT></P>

<P><FONT SIZE=2 FACE="Arial">Regards,</FONT>
</P>
<BR>

<P><FONT SIZE=2 FACE="Arial">Paavo.</FONT>
</P>
<BR>

</BODY>
</HTML>