Issue
Be informed, I am also using StandardScaler. I'm not sure if that affects anything. I can try to provide reproducible code for that, but perhaps it's not necessary. It may just be a numpy thing.
import numpy as np
x = np.random.rand(60,60,1)
Now we plot this, to see the image.
cs = plt.imshow(x)
plt.colorbar()
plt.show()
We do this with imshow, which does accept 3D arrays. We need to use contourf, though, which only accepts 2D arrays.
x = x.reshape(1, 60*60)
Now, I want to plot this, so I want to get it into (60,60)
. But if I just reshape back to (60,60)
, the image is distorted.
x = x.reshape(60,60)
cs = plt.contourf(x)
plt.colorbar()
plt.show()
I am specifically asking to reshape it so that 1. It was the same image as the first image, and 2. So that it could be done with contourf, since that this the only function for which a custom color bar is available AFAIK. One can see that the images are different because the max on each color bar is different (0.8 vs 1.05)
Solution
Your question touches on several different topics, it would help if it was more specific.
First, regarding the shape, I would always try to avoid reshaping yourself (manually), that's only error prone and requires either hard coding the shape or retrieving it with something like x.shape
etc.
In this case, you can simply drop the redundant "band" dimension by using:
x = np.squeeze(x)
That makes Numpy do the work, and preserves the other dimensions as they are.
Secondly, note that imshow
and contourf
have a different default origin. You can see this in your post because one image is vertically flipped compared to the other. This becomes obvious if you introduce some "artifact" in your random array.
You can explicitly define the origin yourself if you want control over this.
Lastly, the colors for contourf
are created by specifying a range (low, high) for the values in between to get a certain color. This is somewhat different compared to the more continuous mapping when using imshow
. But you can pass a BoundaryNorm
to imshow
to make it behave similar to contourf
.
Sample data:
x = np.random.rand(20, 20, 1)
x[2:8, 2:8] += 0.4
x = np.clip(x, 0, 1)
x = np.squeeze(x)
Colormap and Normalizer:
cmap = plt.cm.viridis
bounds = np.linspace(0, 1, 11)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
Plot result:
fig, (ax1, ax2) = plt.subplots(
1,2, figsize=(10,5), constrained_layout=True,
subplot_kw=dict(xticks=[], yticks=[], aspect=1),
)
im = ax1.imshow(x, cmap=cmap, norm=norm, origin='upper')
cb = fig.colorbar(im, ax=ax1, orientation='horizontal', shrink=0.5, spacing='proportional')
cs = ax2.contourf(x, cmap=cmap, norm=norm, levels=bounds, origin='upper')
cb = fig.colorbar(cs, ax=ax2, orientation='horizontal', shrink=0.5, spacing='proportional')
The interpolation from contourf
will "erode" the highs and lows a little, making it appear to have slightly less contrast/range.
Answered By - Rutger Kassies
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.