Combining properties of pcolormesh and imshow
Question:
An advantage of plt.pcolormesh over plt.imshow is the possibility to have unequal axis spacing.
On the other hand, plt.imshow‘s advantage over plt.pcolormesh is that it can display RGB-triplets.
Now, the predicament I am in is that I need to plot RGB-triplets with uneven axis spacing….
Below is a MWE:
import numpy as np
import matplotlib.pyplot as plt
from colorsys import hsv_to_rgb
square_x_axis = np.linspace(0,1,100)**2
cube_y_axis = np.linspace(0,1,200)**3
X,Y = np.meshgrid(cube_y_axis,square_x_axis); print(f'meshgrid has shape: {X.shape}')
rgb_array = np.zeros((square_x_axis.size, cube_y_axis.size,3)); print(f'rgb_array has shape: {rgb_array.shape}')
""" Now we populate the rgb array (initially in hsv color space for clarity)"""
for i,row in enumerate(rgb_array):
for j,col in enumerate(row):
rgb_array[i,j,:] = np.array(hsv_to_rgb(0,square_x_axis[i],cube_y_axis[j]))
fig = plt.figure(figsize=(15,10))
imshow_ax = plt.subplot(1,2,1)
imshow_ax.imshow(rgb_array, aspect='auto', extent=[0,1,0,1])
pcolor_R_ax = plt.subplot(3,2,2)
pcolor_R_ax.pcolormesh(X,Y,rgb_array[:,:,0], cmap='Reds')
pcolor_G_ax = plt.subplot(3,2,4)
pcolor_G_ax.pcolormesh(X,Y,rgb_array[:,:,1], cmap='Greens')
pcolor_B_ax = plt.subplot(3,2,6)
pcolor_B_ax.pcolormesh(X,Y,rgb_array[:,:,2], cmap='Blues')
Which produces the following figure:
The problem becomes immediately obvious: imshow (on the left) is capable of representing the 3D array, but its axis are scaled wrong, leading to a distorted representation. pcolormesh (on the right), on the other hand, can not represent the 3D array (hence why I plot all three channels separately), but is capable of applying the axis correctly, leading to no distortion.
How can I combine these properties?
Answers:
I found another answer here that seems to work on your example, with a small tweak for some new pcolorbesh
behaviour (the shading='auto'
bit). Try this plot on your data:
fig = plt.figure(figsize=(15,10))
placeholder = rgb_array[..., 0]
colors = rgb_array.reshape(-1, 3)
mesh = plt.pcolormesh(X, Y, placeholder, facecolors=colors, shading='auto')
mesh.set_array(None)
It produces:
@kwinkunks answer is the method that solved my problem:
The original data, using imshow
, looked like this, where both the x- and y-axis of the data plot and the colorbar are wrong. Of all 4 axes, only the data y-axis is linear, the 3 other axes are non-linear, and so using imshows
‘s extent
option is no good:
Now… taking @kwinkunks answer directly produced the following plot:
…where the axes tickmarks are now as they should be! Amazing!
An advantage of plt.pcolormesh over plt.imshow is the possibility to have unequal axis spacing.
On the other hand, plt.imshow‘s advantage over plt.pcolormesh is that it can display RGB-triplets.
Now, the predicament I am in is that I need to plot RGB-triplets with uneven axis spacing….
Below is a MWE:
import numpy as np
import matplotlib.pyplot as plt
from colorsys import hsv_to_rgb
square_x_axis = np.linspace(0,1,100)**2
cube_y_axis = np.linspace(0,1,200)**3
X,Y = np.meshgrid(cube_y_axis,square_x_axis); print(f'meshgrid has shape: {X.shape}')
rgb_array = np.zeros((square_x_axis.size, cube_y_axis.size,3)); print(f'rgb_array has shape: {rgb_array.shape}')
""" Now we populate the rgb array (initially in hsv color space for clarity)"""
for i,row in enumerate(rgb_array):
for j,col in enumerate(row):
rgb_array[i,j,:] = np.array(hsv_to_rgb(0,square_x_axis[i],cube_y_axis[j]))
fig = plt.figure(figsize=(15,10))
imshow_ax = plt.subplot(1,2,1)
imshow_ax.imshow(rgb_array, aspect='auto', extent=[0,1,0,1])
pcolor_R_ax = plt.subplot(3,2,2)
pcolor_R_ax.pcolormesh(X,Y,rgb_array[:,:,0], cmap='Reds')
pcolor_G_ax = plt.subplot(3,2,4)
pcolor_G_ax.pcolormesh(X,Y,rgb_array[:,:,1], cmap='Greens')
pcolor_B_ax = plt.subplot(3,2,6)
pcolor_B_ax.pcolormesh(X,Y,rgb_array[:,:,2], cmap='Blues')
Which produces the following figure:
The problem becomes immediately obvious: imshow (on the left) is capable of representing the 3D array, but its axis are scaled wrong, leading to a distorted representation. pcolormesh (on the right), on the other hand, can not represent the 3D array (hence why I plot all three channels separately), but is capable of applying the axis correctly, leading to no distortion.
How can I combine these properties?
I found another answer here that seems to work on your example, with a small tweak for some new pcolorbesh
behaviour (the shading='auto'
bit). Try this plot on your data:
fig = plt.figure(figsize=(15,10))
placeholder = rgb_array[..., 0]
colors = rgb_array.reshape(-1, 3)
mesh = plt.pcolormesh(X, Y, placeholder, facecolors=colors, shading='auto')
mesh.set_array(None)
It produces:
@kwinkunks answer is the method that solved my problem:
The original data, using imshow
, looked like this, where both the x- and y-axis of the data plot and the colorbar are wrong. Of all 4 axes, only the data y-axis is linear, the 3 other axes are non-linear, and so using imshows
‘s extent
option is no good:
Now… taking @kwinkunks answer directly produced the following plot:
…where the axes tickmarks are now as they should be! Amazing!