-2

I am trying to work in Python 3 with topography/bathymetry-information (basically a grid containing x [longitude in decimal degrees], y [latitude in decimal degrees] and z [meter]).

The grid file has the extension .nc and is therefore a netCDF-file. Normally I would use it in mapping tools like Generic Mapping Tools and don't have to bother with how a netCDF file works, but I need to extract specific information in a Python script. Right now this is only limiting the dataset to certain longitude/latitude ranges.

However, right now I am a bit lost on how to get to the z-information for specific x and y values. Here's what I know about the data so far

import netCDF4

#----------------------
# Load netCDF file
#----------------------
bathymetry_file = 'C:/Users/te279/Matlab/data/gebco_08.nc'
fh = netCDF4.Dataset(bathymetry_file, mode='r')

#----------------------
# Getting information about the file
#----------------------
print(fh.file_format)

NETCDF3_CLASSIC

print(fh)

root group (NETCDF3_CLASSIC data model, file format NETCDF3): title: GEBCO_08 Grid source: 20100927 dimensions(sizes): side(2), xysize(933120000) variables(dimensions): float64 x_range(side), float64 y_range(side), int16 z_range(side), float64 spacing(side), int32 dimension(side), int16 z(xysize) groups:

print(fh.dimensions.keys()) 

odict_keys(['side', 'xysize'])

print(fh.dimensions['side'])

: name = 'side', size = 2

print(fh.dimensions['xysize'])

: name = 'xysize', size = 933120000

#----------------------
# Variables
#----------------------
print(fh.variables.keys()) # returns all available variable keys

odict_keys(['x_range', 'y_range', 'z_range', 'spacing', 'dimension', 'z'])

xrange = fh.variables['x_range'][:] 
print(xrange)

[-180. 180.] # contains the values -180 to 180 for the longitude of the whole world

yrange = fh.variables['y_range'][:]
print(yrange) 

[-90. 90.] # contains the values -90 to 90 for the latitude of the whole world

zrange = fh.variables['z_range'][:]

[-10977 8685] # contains the depths/topography range for the world

spacing = fh.variables['spacing'][:] 

[ 0.00833333 0.00833333] # spacing in both x and y. Equals the dimension, if multiplied with x and y range

dimension = fh.variables['dimension'][:] 

[43200 21600] # corresponding to the shape of z if it was the 2D array I would've hoped for (it's currently an 1D array of 9333120000 - which is 43200*21600)

z = fh.variables['z'][:] # currently an 1D array of the depth/topography/z information I want
fh.close

Based on this information I still don't know how to access z for specific x/y (longitude/latitude) values. I think basically I need to convert the 1D array of z into a 2D array corresponding to longitude/latitude values. I just have not a clue how to do that. I saw in some posts where people tried to convert a 1D into a 2D array, but I have no means to know in what corner of the world they start and how they progress.

I know there is a 3 year old similar post, however, I don't know how to find an analogue "index of the flattened array" for my problem - or how to exactly work with that. Can somebody help?

2 Answers 2

0

You need to first read in all three of z's dimensions (lat, lon, depth) and then extract values across each of those dimensions. Here are a few examnples.

# Read in all 3 dimensions [lat x lon x depth] 
z = fh.variables['z'][:,:,:] 

# Topography at a single lat/lon/depth (1 value):
z_1 = z[5,5,5]

# Topography at all depths for a single lat/lon (1D array):
z_2 = z[5,5,:] 

# Topography at all latitudes and longitudes for a single depth (2D array):
z_3 = z[:,:,5] 

Note that the number you enter for lat/lon/depth is the index in that dimension, not an actual latitude, for instance. You'll need to determine the indices of the values you are looking for beforehand.

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately neither Lat nor Long could be read directly, the only variable with more than two values was z, the 1D array
I tried it just to be sure and I got the error "ValueError: slicing expression exceeds the number of dimensions of the variable".
0

I just found the solution in this post. Sorry that I didn't see that before. Here's what my code looks like now. Thanks to Dave (he answered his own question in the post above). The only thing I had to work on was that the dimensions have to stay integers.

import netCDF4
import numpy as np

#----------------------
# Load netCDF file
#----------------------
bathymetry_file = 'C:/Users/te279/Matlab/data/gebco_08.nc'
fh = netCDF4.Dataset(bathymetry_file, mode='r')

#----------------------
# Extract variables
#----------------------
xrange = fh.variables['x_range'][:] 
yrange = fh.variables['y_range'][:]
zz = fh.variables['z'][:] 
fh.close()

#----------------------
# Compute Lat/Lon
#----------------------
nx = (xrange[-1]-xrange[0])/spacing[0]   # num pts in x-dir
ny = (yrange[-1]-yrange[0])/spacing[1]   # num pts in y-dir
nx = nx.astype(np.integer)
ny = ny.astype(np.integer)
lon = np.linspace(xrange[0],xrange[-1],nx)
lat = np.linspace(yrange[0],yrange[-1],ny)

#----------------------
# Reshape the 1D to an 2D array
#----------------------
bathy = zz[:].reshape(ny, nx)

So, now when I look at the shape of both zz and bathy (following code), the former is a 1D array with a length of 933120000, the latter the 2D array with dimensions of 43200x21600.

print(zz.shape)
print(bathy.shape)

The next step is to use indices to access the bathymetry/topography data correctly, just as N1B4 described in his post

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.