[netcdfgroup] Reading netcdf files via VB6?

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

 

 

 

  • 2008 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the netcdfgroup archives: