-
Notifications
You must be signed in to change notification settings - Fork 369
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
imshow
fails when transform projection is different that the axes projection
#2480
Comments
Digging a little in geoaxis.py I noticed that the image reprojection is dependent on the plot extent. Setting the map extent before adding the raster data with cartopy/lib/cartopy/mpl/geoaxes.py Lines 1290 to 1305 in 0d4e39f
Below is an example of this, adapting from the Reprojecting Images example in the docs
Codeimport numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cf
def dummy_image():
"""
Return a 2x2 dummy image with a projection and extent.
Returns
-------
img : numpy array
The pixels of the image in a numpy array.
img_proj : cartopy CRS
The rectangular coordinate system of the image.
img_extent : tuple[float, float, float, float]
The extent of the image ``(left, right, bottom, top)`` referenced in
the ``img_proj`` coordinate system.
origin : str
The origin of the image to be passed through to matplotlib's imshow.
"""
img = np.linspace(0, 1, 12).reshape(6, 2)
img_proj = ccrs.PlateCarree()
img_extent = (-87.6, -86.4, 41.4, 42.0)
return img, img_proj, img_extent, "lower"
def buggy_map(axes_proj):
fig, ax = plt.subplots(subplot_kw={"projection": axes_proj})
# Add some map features
ax.add_feature(cf.LAKES, alpha=0.3)
ax.add_feature(cf.STATES)
# Add the image before the extent of the map is set
img, crs, extent, origin = dummy_image()
ax.imshow(img, transform=crs, extent=extent, origin=origin, cmap="spring")
## Add raster corners
ax.scatter(
extent[:2],
extent[2:],
transform=ccrs.PlateCarree(),
s=100,
c="k",
marker="x",
label="imshow extent",
)
# Set the map extexts after imshow
map_extent = (-88, -86, 41.2, 42.2)
ax.set_extent(map_extent, crs=ccrs.PlateCarree())
# Final touches
ax.gridlines(draw_labels=True)
ax.set_title(f"\u2717 Using {type(axes_proj)}")
ax.legend()
fig.savefig("buggy_map.png")
def not_buggy_map(axes_proj):
fig, ax = plt.subplots(subplot_kw={"projection": axes_proj})
# Set the map extexts before imshow
map_extent = (-88, -86, 41.2, 42.2)
ax.set_extent(map_extent, crs=ccrs.PlateCarree())
# Add the image *after* the extent of the map is set
img, crs, extent, origin = dummy_image()
ax.imshow(img, transform=crs, extent=extent, origin=origin, cmap="spring")
# Add some map features
ax.add_feature(cf.LAKES, alpha=0.3)
ax.add_feature(cf.STATES)
## Add raster corners
ax.scatter(
extent[:2],
extent[2:],
transform=ccrs.PlateCarree(),
s=100,
c="k",
marker="x",
label="imshow extent",
)
# Final touches
ax.gridlines(draw_labels=True)
ax.set_title(f"\u2713 Using {type(axes_proj)}")
ax.legend()
fig.savefig("not_buggy_map.png")
def main():
axes_proj = ccrs.LambertConformal(central_longitude=-87, central_latitude=41.7)
buggy_map(axes_proj)
not_buggy_map(axes_proj)
if __name__ == "__main__":
main() I have not found this being mentioned in the documentation though. Should a note be added? |
Description
imshow
works fine when both axes and raster data projections are the same (Figure 1), but it fails when the axes has a projection that is different from the data (Figure 2). As a workaround, the data extent has to be projected independently to the axes projection and pass that as the extent toimshow
(Figure 3)To reproduce
Code
Environment
PD:
#2459 seemed related but I am afraid this is a separate issue.
The text was updated successfully, but these errors were encountered: