NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.
To learn about what's going on, see About the Archive Site.
Dear netcdf users: Does anyone out there have experience reading netcdf files via VB6? I'm developing a VB6 application that will provide precipitation, temperature and crop evapotranspiration data over the Ogallala aquifer region. The meteorological data I'm using is daily U.S. Historical Climatology Network Data from 135 meteorological stations during 1971-2000. This data was loaded into a netcdf file called 'OGDATA.NC' on a Linux workstation. I then installed the Win32 netcdf.dll, and the ncgen, and ncdump (ver 3.6.1) utilities on a PC running Windows XP. When I transferred OGDATA.NC to the Windows box and dumped it via ncdump everything seems OK. Results for ncdump -c OGDATA.NC netcdf OGDATA { dimensions: DAYS = 365 ; YEAR = 30 ; STATIONS = 135 ; nchar6 = 6 ; variables: short TMAX(STATIONS, YEAR, DAYS) ; short TMIN(STATIONS, YEAR, DAYS) ; short DPCP(STATIONS, YEAR, DAYS) ; float latitude(STATIONS) ; float longitude(STATIONS) ; int elevation(STATIONS) ; char StationID(STATIONS, nchar6) ; data: } After poking around the Unidata netcdf web site and googling 'netcdf and VB6' I found Carsten Wieczorrek's web page (http://www.mn-net.com/tabid/10844/default.aspx ), which describes some problems and fixes for reading netcdf files via VB6 code. According to my reading of this web page, VB6 arrays such as the corner and edge array arguments to nectdf functions contain additional header bytes for every dimension and are not suitable for the Win32 netcdf dll. From that page: " ...netcdf.dll requires dimids as C-array (4 bytes for every element). The VB-array dimids() contains some header bytes for every dimension and they are not suitable for the dll...". A fix is proposes where multi-element long integer arrays are handled as strings. "... A C-long variable contains four bytes. So your string needs 4 bytes for every array-element. For example, your variable is two-dimensional with the varids Variable_1_ID = 3 and Variable_2_ID = 5. The bits in a long variable with value = 3 are equal to 11000000 | 00000000 | 00000000 | 00000000 and that is equal to a 4 byte string with character(3) & character(0) & character(0) & character(0)..." I'm a little unclear on this, as character(0) in the ascii set maps to Decimal 48, which should be (?) 00001100 | 00000000 | 00000000 | 00000000 in binary Maybe I'm not accounting for endian-ness. At any rate, I've tried this fix in the following code but it doesn't seem to be working. I've found that I can open the file, and retrieve the file and variable ID numbers. But when I try to read just the array containing the latitudes of the stations I just get 0's as output. My stripped down VB6 test code is as follows: ------------------------------------------------------------------------ ------------------------- ' VB6 code to test read OGDATA.NC Option Explicit 'nc_open /* open existing netCDF dataset */ Private Declare Function nc_open "netcdf.dll" _ (ByVal path As String, ByVal mode As Long, ByRef ncid As Long) As Long 'nc_inq_varid /* get variable IDs */ Private Declare Function nc_inq_varid Lib "netcdf.dll" _ (ByVal ncid As Long, ByVal name As String, ByRef varid As Long) As Long ' nc_get_vara_float with string edges and corner array arguments... 'Private Declare Function nc_get_vara_float Lib "netcdf.dll" _ (ByVal ncid As Long, ByVal varid As Long, ByVal corner As String, ByVal edges As String, ByRef ip As Single) As Long 'nc_close /* close netCDF dataset */ Private Declare Function nc_close Lib "netcdf.dll" (ByRef ncid As Long) As Long Const ndays As Integer = 365 Const nyrs As Integer = 30 ' 1971-2000 in OGDATA.NC Const nsta As Integer = 135 Const ndim As Integer = 3 Dim ncid As Long Dim lon_id As Long Dim lat_id As Long Dim elev_id As Long Dim stn_id As Long Dim dpcp_id As Long Dim tmin_id As Long Dim tmax_id As Long Dim ista As Long Dim lon(1 To nsta) As Single Dim corner(1 To 3) As Long Dim edges(1 To 3) As Long Public Sub Form_Load() Open "test_netcdf.txt" For Output As #1 Infile = "OGDATA.NC" On Error Resume Next res = nc_open(Infile, 0, ncid) On Error Resume Next res = nc_inq_varid(ncid, "latitude", lat_id) On Error Resume Next res = nc_inq_varid(ncid, "longitude", lon_id) On Error Resume Next res = nc_inq_varid(ncid, "elevation", elev_id) On Error Resume Next res = nc_inq_varid(ncid, "StationID", stn_id) On Error Resume Next res = nc_inq_varid(ncid, "DPCP", dpcp_id) On Error Resume Next res = nc_inq_varid(ncid, "TMIN", tmin_id) On Error Resume Next res = nc_inq_varid(ncid, "TMAX", tmax_id) Write #1, "Lat_ID " & lat_id Write #1, "Lon_ID " & lon_id Write #1, "Elev_ID " & elev_id Write #1, "Sta_ID " & stn_id Write #1, "DPCP_ID " & dpcp_id Write #1, "TMIN_ID " & tmin_id Write #1, "TMAX_ID " & tmax_id Write #1, " " ' This corner & edges scheme was adopted from ' Carsten Wieczorrek's web page... corner_1_val = 1 corner1 = Chr(corner_1_val) & Chr(0) & Chr(0) & Chr(0) edges_1_val = nsta edges1 = Chr(edges_1_val) & Chr(0) & Chr(0) & Chr(0) On Error Resume Next Call nc_get_vara_float(ncid, lon_id, corner1, edges1, lon(1)) For ista = 1 To nsta ' Print #1, "--- "; Format(ista, "####"); lon(ista) Next ista On Error Resume Next res = nc_close(ncid) End Sub '----------------------------------------------------------------------- ------------------------- This code produces the following output in test_netcdf.txt "Lat_ID 3" "Lon_ID 4" "Elev_ID 5" "Sta_ID 6" "DPCP_ID 2" "TMIN_ID 1" "TMAX_ID 0" " " --- 1 0 --- 2 0 --- 3 0 --- 4 0 --- 5 0 --- 6 0 --- 7 0 --- 8 0 --- 9 0 --- 10 0 --- 11 0 --- 12 0 --- 13 0 --- 14 0 --- 15 0 --- 16 0 ... ... --- 135 0 ------------------------------------------------------------------------ ----------------------- Clearly something is wrong there... So going back to the Unidata archives I Saw another post by Matthew Hanna ("Index mapping for VB6") where it seemed that this fix of substituting character strings for arrays was unnecessary.... In that post you'll find: > Public Declare Function nc_get_varm_double Lib "netcdf.dll" (ByVal ncid > As Long, ByVal varid As Long, ByRef startp As Long, ByRef countp As > Long, ByRef stridep As Long, ByRef imapp As Long, ByRef ip As Double) As > Long > NcErr = nc_get_varm_double(fHandle, var_id, dims(1), count(1), > stride(1), imap(1), dblArray(1, 1)) > If NcErr <> 0 Then GoTo NcErrOut So I went ahead and gave that approach a try in my test VB6 code by making the following changes... 'nc_get_var_long /* get arrays of floating point */ Private Declare Function nc_get_vara_float Lib "netcdf.dll" _ (ByVal ncid As Long, ByVal varid As Long, ByRef corner_p As Long, ByRef edges_p As Long, ByRef fl_p As Single) As Long corner(1) = 1 edges(1) = nsta On Error Resume Next Call nc_get_vara_float(ncid, lon_id, corner(1), edges(1), lon(1)) This produced the same results as found above. Can anyone with netcdf + VB6 experience see what I'm doing wrong? Thanks in Advance for any Advice, Steve Mauget
netcdfgroup
archives: