1

I have created a GeoTIFF file using the code below.

Part1: code for GeoTIFF creation.

import numpy as np
import pandas as pd
import rasterio as rio

# Define the range of latitudes and longitudes
lat_range = (39, 41)
lon_range = (-76, -73)

# Define the resolution of the grid
resolution = 0.1

# Create arrays of the latitude and longitude values
lats = np.arange(lat_range[0], lat_range[1], resolution)
lons = np.arange(lon_range[0], lon_range[1], resolution)

# Create a meshgrid of the latitude and longitude values
lon_mesh, lat_mesh = np.meshgrid(lons, lats)

# Flatten the meshgrids into 1D arrays of latitude and longitude values
lat_values = lat_mesh.flatten()
lon_values = lon_mesh.flatten()

# Generate random z values for each latitude and longitude pair
z_values = np.random.rand(len(lat_values))

# Create a pandas DataFrame to store the data
data = pd.DataFrame({'lat': lat_values, 'lon': lon_values, 'z': z_values})

# Define the GeoTIFF file parameters
width = len(lons)
height = len(lats)
transform = rio.transform.from_bounds(lon_range[0], lat_range[0], lon_range[1], lat_range[1], width, height)
crs = rio.crs.CRS.from_epsg(4326)  # WGS 1984

# Write the GeoTIFF file
with rio.open("output.tif", "w", driver="GTiff", width=width, height=height, count=1, dtype=np.float32, nodata=0, transform=transform, crs=crs) as dst:
    # Reshape the z values into a 2D array and write them to the GeoTIFF file
    z_array = z_values.reshape((height, width))
    dst.write(z_array, 1)

Then used the following code to extract the values from the above geotiff file stored as output.tif.

Part2: code for extraction.

import rasterio as rio
import pandas as pd
import geopandas as gpd
import numpy as np

# Load the GeoTIFF file
with rio.open(r"E:\\Machine_Learning_for_Himalaya_IEEE_GRSL\\plots\\output.tif") as src:
    # Extract the metadata for the file
    meta = src.meta
    print("meta:",meta)
    # Define the latitude and longitude ranges
    lat_range = (39, 41)
    lon_range = (-76, -73)

    # Create a grid of points with a 0.1 degree interval within the specified ranges
    lats = np.arange(lat_range[0], lat_range[1], 0.1)
    lons = np.arange(lon_range[0], lon_range[1], 0.1)
    lon_mesh, lat_mesh = np.meshgrid(lons, lats)
    geometry = gpd.points_from_xy(lon_mesh.ravel(), lat_mesh.ravel())
    points = gpd.GeoDataFrame(geometry=geometry)

    # Extract the z values at the point locations using rasterio.sample
    zs = list(src.sample(zip(points.geometry.x, points.geometry.y)))

    # Create a Pandas DataFrame to store the point coordinates and values
    df = pd.DataFrame({'Latitude': lat_mesh.ravel(),
                       'Longitude': lon_mesh.ravel(),
                       'Value': zs})

print(df)

The outputs are as follows: for the second part following is output:

meta: {'driver': 'GTiff', 'dtype': 'float32', 'nodata': 0.0, 'width': 30, 'height': 20, 'count': 1, 'crs': CRS.from_epsg(4326), 'transform': Affine(0.1, 0.0, -76.0,
       0.0, -0.1, 41.0)}
     Latitude  Longitude        Value
0        39.0      -76.0        [0.0]
1        39.0      -75.9        [0.0]
2        39.0      -75.8        [0.0]
3        39.0      -75.7        [0.0]
4        39.0      -75.6        [0.0]
..        ...        ...          ...
595      40.9      -73.5  [0.5188609]
596      40.9      -73.4   [0.589194]
597      40.9      -73.3  [0.5691334]
598      40.9      -73.2  [0.8172998]
599      40.9      -73.1  [0.5687353]

[600 rows x 3 columns]

If we print the dataframe i.e., data from the Part1 code, the output is as below.

      lat   lon         z
0    39.0 -76.0  0.613836
1    39.0 -75.9  0.002668
2    39.0 -75.8  0.432013
3    39.0 -75.7  0.912882
4    39.0 -75.6  0.892871
..    ...   ...       ...
595  40.9 -73.5  0.170039
596  40.9 -73.4  0.340669
597  40.9 -73.3  0.809385
598  40.9 -73.2  0.501880
599  40.9 -73.1  0.085377

[600 rows x 3 columns]

We can clearly see the values are different for same coordinates in the above outputs. How to sort this and why this is happening?

1 Answer 1

0

It's because your points are falling exactly on the corners of the pixels.

enter image description here

If you offset them by half a pixel in the x & y dimension, you'll get the right answer.

    # Create a grid of points with a 0.1 degree interval within the specified ranges
    lats = np.arange(lat_range[0], lat_range[1], 0.1) + 0.05  # offset by 1/2 pixel
    lons = np.arange(lon_range[0], lon_range[1], 0.1) + 0.05

enter image description here

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.