Retrieve pixel value using SNAP-engine and Python for specific geographic coordinates

Hi all,
I’m trying to retrieve pixel values in Sentinel-3 data for specific geographic coordinates using the SNAP-Engine. Until now, I transform the geographic coordinates to the corresponding X and Y with the following code using these links:

https://stackoverflow.com/questions/51194477/converting-geographical-coordinates-long-lat-to-pixel-position-x-y-for-a-se
https://senbox.atlassian.net/wiki/spaces/SNAP/pages/19300362/How+to+use+the+SNAP+API+from+Python))

I have written the following code:

import sys
sys.path.append('/path/to/.snap/snap-python')
from snappy import ProductIO
import numpy as np
from snappy import GeoPos

p = ProductIO.readProduct('/path/to/file.xml')
iwv = p.getBand('IWV')

g = p.getSceneGeoCoding()

def XY_from_LatLon(ProductSceneGeoCoding, latitude, longitude):
    #From Latitude, Longitude satellite image, get the x, y position in image
    pixelPos = ProductSceneGeoCoding.getPixelPos(GeoPos(latitude, longitude), None)
    x = pixelPos.getX()
    y = pixelPos.getY()
    if str(x)=='nan':
        raise ValueError('Latitude or Longitude out of this product')
     else:
         return x, y

    x, y = XY_from_LatLon(sg, <lat>, <lon>)
    print(iwv.getPixelFloat(x, y))

But it raises the following error:


    Traceback (most recent call last):
    File "snap.py", line 28, in <module> 
    print(iwv.getPixelInt(x, y))
    RuntimeError: no matching Java method overloads found

How can I fix that ?
Thank you in advance!
1 Like

Hello there @Gpetrak, I don’t know if you have found a fix to your problem, but I think I have an alternative solution.

I needed to do extract pixel values from S3 images given LON/LAT positions, but I did not used snappy for that at the time. Here is what I did:

  1. The geo_coordinates.nc file contains the spatial information of your image matrix, we are going to need that since we want a specific lat/lon point:
from netCDF4 import Dataset  # http://code.google.com/p/netcdf4-python/

nc_coord = Dataset('/path/to/your/S3_IMAGE.SEN3/geo_coordinates.nc', 'r')
  1. Now we need to convert that to unmasked Pandas DataFrames:
lat = nc_coord.variables['latitude'][:]
lat = lat.data
lon = nc_coord.variables['longitude'][:]
lon = lon.data 
  1. We have the LAT and LON as dataframe variables, now we need the data from the actual bands:
nc_file = Dataset('/path/to/your/S3_IMAGE.SEN3/Oa01_radiance.nc', 'r')
bname = 'Oa01_radiance'
extrated_band = nc_file.variables[bname][:]
nc_file.close()  # it is good practice to close the netcdf after using it (:
  1. Now that we have it all in DataFrames, lets extract the pixel value in you position of interest:
# define your point:
target_lon, target_lat = -60.014493, -3.158980

import numpy as np
# lat and lon are x,y matrices, we will add another dimension z in order to stack them
lat = lat[:, :, np.newaxis]
lon = lon[:, :, np.newaxis]
grid = np.concatenate([lat, lon], axis=2)
vector = np.array([target_lat, target_lon]).reshape(1, 1, -1)
subtraction = vector - grid

# vector subtraction
dist = np.linalg.norm(subtraction, axis=2)

# query where in the 2D matrix is the closest point to your points of interest?
result = np.where(dist == dist.min())

# this is your lat/lon geo point translated to a x,y position in the image matrix
target_x_y = result[0][0], result[1][0]

# query your raw image band DataFrame using the matrix position instead of the geo position
pixel_value = extrated_band[target_x_y]

pixel_value should now contain the radiance information from the Oa01_radiance.nc in your given target_lon, target_lat position.

This is not pretty code and is just extracting data from a single band, but I hope it helps somehow.

If instead you want to extract the data inside all the pixels of a given region of interest, I suggest you read @marpet answer here: Pixel extraction from many SENTINEL-3 products in SNAP

2 Likes

@daviguima, Thank you so much for this helpful answer ! It works !

1 Like