Search code examples
pythongdalmatplotlib-basemap

how to plot geotiff data in specific area (lat/lon) with python


I have a geotiff raster data sets with elevation data init and i want to plot it in specific area, such as 60°E - 70° E ,70°S - 80°E.

I have a bit of code from here,but the pcolormesh seem couldn't plot my geotif.it's all red. picture. The picture is shown by imshow as really picture

When I try to make a plot with this code below:

path = "F:\\Mosaic_h1112v28_ps.tif"
dataset = gdal.Open(path)
data = dataset.ReadAsArray()
x0, dx, dxdy, y0, dydx, dy = dataset.GetGeoTransform()
nrows, ncols = data.shape
londata = np.linspace(x0, x0+dx*ncols)
latdata = np.linspace(y0, y0+dy*nrows)
lons, lats = np.meshgrid(lonarray, latarray)  
fig = plt.figure(figsize=(8, 8))
m = Basemap(projection='lcc', lon_0=67.5, lat_0=-68.5, height=950000,
            width=580000, resolution='h') 
m.drawcoastlines() 
x, y = m(lons, lats) 

Then i dont know how to continue it . I just want to use imshow, but the imshow dont specify area(lat/lon).

I will really appreciate your help.


Solution

  • It's a good question, here is my solution.

    Required packages: georaster with its dependencies (gdal, etc).
    Data for demo purposes downloadable from http://dwtkns.com/srtm/

    import georaster
    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap
    
    fig = plt.figure(figsize=(8,8))
    
    # full path to the geotiff file
    fpath = r"C:\\path_to_your\geotiff_file\srtm_57_10.tif"  # Thailand east
    
    # read extent of image without loading
    # good for values in degrees lat/long
    # geotiff may use other coordinates and projection
    my_image = georaster.SingleBandRaster(fpath, load_data=False)
    
    # grab limits of image's extent
    minx, maxx, miny, maxy = my_image.extent
    
    # set Basemap with slightly larger extents
    # set resolution at intermediate level "i"
    m = Basemap( projection='cyl', \
                llcrnrlon=minx-2, \
                llcrnrlat=miny-2, \
                urcrnrlon=maxx+2, \
                urcrnrlat=maxy+2, \
                resolution='i')
    
    m.drawcoastlines(color="gray")
    m.fillcontinents(color='beige')
    
    # load the geotiff image, assign it a variable
    image = georaster.SingleBandRaster( fpath, \
                            load_data=(minx, maxx, miny, maxy), \
                            latlon=True)
    
    # plot the image on matplotlib active axes
    # set zorder to put the image on top of coastlines and continent areas
    # set alpha to let the hidden graphics show through
    plt.imshow(image.r, extent=(minx, maxx, miny, maxy), zorder=10, alpha=0.6)
    
    plt.show()
    

    The resulting plot:

    enter image description here

    Edit1

    My original answer places focus on how to plot simple geotiff image on the most basic projection with Basemap. A better answer was not possible without access to all required resources (i.e. geotiff file).

    Here I try to improve my answer.

    I have clipped a small portion from whole world geotiff file. Then reproject (warp) it to LCC projection specifications defined by Basemap() to be used. All the process were done with GDAL softwares. The resulting file is named "lcc_2.tiff". With this geotiff file, the plotting of the image is done with the code below.

    The most important part is that geotiff file must have the same coordinate system (same projection) as the projection used by Basemap.

    import georaster
    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap
    
    fig = plt.figure(figsize=(8,8))
    
    m = Basemap(projection='lcc', lon_0=67.5, lat_0=-68.5, \
                height=950000, width=580000, resolution='h')
    
    m.drawcoastlines()
    m.fillcontinents(color='beige')
    
    image = georaster.SingleBandRaster( "lcc_2.tiff", latlon=False)
    plt.imshow(image.r, extent=image.extent, zorder=10, alpha=0.6)
    
    plt.show()
    

    The output map:

    enter image description here