Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sampling interval is irregular when loading Raster with downsampling option #447

Open
adehecq opened this issue Jan 24, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@adehecq
Copy link
Member

adehecq commented Jan 24, 2024

Describe the bug
When loading a raster with geoutils.Raster(filename, downsample=6), one can expect that the pixels are sampled every 6 pixels, without interpolation. This is not the case.

To Reproduce

The best way to test this, is to create a Raster with data that increases linearly along lines and/or columns. Here I create a raster that has a gradient of 1 along rows and 100 along lines. I save this raster and open it with downsampling option. The gradient of the output should be 1*downsample along rows and 100*downsample along columns, but when the shape is not a multiple of downsample, it does not work.
For example:

import geoutils as gu
import numpy as np
import matplotlib.pyplot as plt
import rasterio as rio
from tempfile import NamedTemporaryFile

# Create a fake Raster with 
# row1: 0, 1, 2, 3... 99
# row2: 100, 101, ... 199 etc
data = np.arange(5000).reshape((50, 100))
transform = rio.transform.from_bounds(0, 0, 100, 50, 100, 50)
rst = gu.Raster.from_array(data, crs="EPSG:4326", transform=transform)

# Save to file (needed to open with downsample option
tmpfile = NamedTemporaryFile(suffix=".tif")
rst.save(tmpfile.name)

# Load with a downsampling that is not multiple of 50 or 100
test = gu.Raster(tmpfile.name, downsample=6)

# Plot gradients
fig, axes = plt.subplots(1, 2, figsize=(16, 4))
im1 = axes[0].imshow(np.gradient(test.data.data, axis=0))
plt.colorbar(im1)

im2 = axes[1].imshow(np.gradient(test.data.data, axis=1))
plt.colorbar(im2)
plt.tight_layout()
plt.show()

The output figure is
Figure_1

Expected behavior

The gradient of the downsampled image should be constant.

System (please complete the following information):
Irrelevant

@adehecq adehecq added the bug Something isn't working label Jan 24, 2024
@adehecq
Copy link
Member Author

adehecq commented Jan 24, 2024

The issue is caused by the fact that when downsampling, we are rounding up the shape (here).
So when reading the data a few lines below in _load_rio, an out_shape is given. Because the output is forced to that shape, that is slightly larger than the actual size, it runs a nearest neighbor resampling.
There are two options:

  • take floor instead of ceil when downsampling, to ensure that out_shape is always smaller than the original shape. However, if the out_shape is still not exactly a multiple of the original size, it will always resample. So one also needs to set a window here.
  • read with option boundless=True which allows to read beyond the original size and fill with a fill_value. But once again, I believe the window should also be set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant