Pixel shift in `render_images`
Hello,
When plotting an image, it seems that there is a 0.5-pixel shift. This is not visible for large images but becomes very visible if we zoom in, and, mostly, it gets amplified with transformations (a Scale(1000, 1000) transformation will create a shift of 500 pixels).
Minimum reproducible example
import numpy as np
import spatialdata_plot
import spatialdata
from spatialdata.models import Image2DModel
from spatial_image import SpatialImage
image = SpatialImage(np.zeros((1, 4, 8)), dims=("c", "y", "x"))
image = Image2DModel.parse(image)
sdata = spatialdata.SpatialData(images={"image": image})
sdata.pl.render_images().pl.show()
It should render this image (we see that the image is not reaching (8, 4), but (7.5, 3.5) instead):
Maybe I did something wrong with the x-coords or y-coords? Should we update the coords or they should be fine by default?
Sorry for such a minor issue...
Thanks for reporting!
Maybe related to this: https://github.com/scverse/spatialdata/issues/165. Also, if fixed before, better to add a test so that we verify we don't reintroduce this after https://github.com/scverse/spatialdata/issues/308 is closed.
This is also problematic for the datashader backend, because if an image is rendered before, its limits are used to determine the canvas size => we see an offset of the datashader points compared to what matplotlib would give us (and what the axis labels say!)
e.g.
from spatialdata import SpatialData
from spatialdata.models import Image2DModel, PointsModel
from spatialdata.transformations import Identity
import matplotlib.pyplot as plt
sdata = SpatialData(
images={
"image1": Image2DModel.parse(
np.full((10, 10, 3), fill_value=128), dims=("y", "x", "c")
)
},
points={
"points1": PointsModel.parse(
pd.DataFrame({"y": [0.1, 0.1, 0.9, 0.9], "x": [0.1, 0.9, 0.9, 0.1]}),
transformations={"global": Identity()},
)
},
)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
sdata.pl.render_images().pl.render_points("points1", method="datashader", size=40, color="red").pl.show(ax=ax1, title="datashader")
sdata.pl.render_images().pl.render_points("points1", method="matplotlib", color="red", size=2).pl.show(ax=ax2, title="matplotlib")
gives me:
@timtreis FYI