Hi everyone. I’m trying to create a ternary composition (I have RGB channels as Data Arrays, in a Xarray Dataset) and almost getting things well. Currently, code is like this:
def lambert_azimuthal_rgb_plot(xarray_dataset, title='Empty Title', latitude_cutoff=50, img_multiplier=1):
# Extract the red, green, and blue data arrays
red = xarray_dataset['red'].values
green = xarray_dataset['green'].values
blue = xarray_dataset['blue'].values
# Combine red, green, and blue arrays into an RGB image
rgb = np.dstack((red, green, blue))
# Create a mask to filter out NaN values
mask = np.isnan(rgb).any(axis=2)
# Set NaN values to transparent (0, 0, 0, 0) in RGBA
rgba = np.zeros((rgb.shape[0], rgb.shape[1], 4))
rgba[~mask, :3] = rgb[~mask]
rgba[~mask, 3] = 1 # Set alpha channel to 1 for non-NaN values
# Define the coordinate reference system (CRS) for the data
data_crs = ccrs.PlateCarree()
# Plot the RGB image using cartopy with Lambert Azimuthal Equal Area projection
fig, ax = plt.subplots(figsize=(10, 10),
subplot_kw={'projection': ccrs.LambertAzimuthalEqualArea(central_latitude=90,
central_longitude=0)})
ax.set_title(title)
# Add 50m resolution coastlines and country borders
coastlines_50m = cfeature.NaturalEarthFeature('physical', 'coastline', '50m', edgecolor='black', facecolor='none')
borders_50m = cfeature.NaturalEarthFeature('cultural', 'admin_0_boundary_lines_land', '50m', edgecolor='black', facecolor='none')
ax.add_feature(coastlines_50m, linewidth=1)
ax.add_feature(borders_50m, linestyle=':', linewidth=1)
# Calculate the extent of the data from xarray metadata
extent = [xarray_dataset['x'].min().item(),
xarray_dataset['x'].max().item(),
xarray_dataset['y'].min().item(),
xarray_dataset['y'].max().item()]
# Display the RGBA image
ax.imshow(rgba,
origin='lower', # Using 'lower' as appropriate for this data
extent=extent,
transform=data_crs,
interpolation='none'
)
# Set the extent of the map to include the area of interest
ax.set_extent([-180, 180, latitude_cutoff - 3, 90], crs=data_crs)
# Adding gridlines
gl = ax.gridlines(draw_labels=True, color='gray', alpha=0.5, linestyle='--')
gl.xlocator = plt.FixedLocator(np.arange(-180, 181, 10))
gl.ylocator = plt.FixedLocator(np.arange(50, 91, 10))
gl.xlabel_style = {'size': 10, 'color': 'gray'}
gl.ylabel_style = {'size': 10, 'color': 'gray'}
plt.show()
When calling the plot with lambert_azimuthal_rgb_plot(xr_from_df_arctic, title='RGB Map', latitude_cutoff=50, img_multiplier=1)
, the result is like this:
Things are almost okay, but the results are padded in the longitude (roughly by 10 degrees). However, when I plot the original channels ( ex.: xarray_dataset['red']
) all is on the correct aspect.
Do you have any suggestions on what may be going on? FYI, I have cross-posted this on Cartopy gitter and at the Xarray discussion (RGB image gets padded along dimension when plotting · pydata/xarray · Discussion #9240 · GitHub ); however, @TomNicholas pointed out that it was slightly off-topic, which is why I am posting it here. Also other suggestions on plotting ternary map compositions are welcome.