2

I have data regarding x, y and color values which are all NxM arrays. Normally, when using Polygon function from Matplotlib, it needs to have color values per FACE (which would be a 1xM array) instead of VERTEX. However, my color data is per VERTEX. So, my question is that is there a way to convert my vertex data to single face color data? Or even better, is there a way to plot polygons using color values per vertex instead of per face?

Note: What I want is quite similar to MATLAB's patch function which you can use color values per vertex.

Edit: Below, you can find a data example of one element. A mesh consists of many elements and below is just one of them. X and Y refer to coordinates and C refers to color values of each coordinate. Note that the below arrays are actually stored as columns in the original code as there are many other elements.

import numpy as np

X = np.array([0,0.176611,0.343377,0.366506,0.390424,0.254526,0.117785,0.602218])
Y = np.array([0,0.0248673,0.0436277,0.0834644,0.123043,0.110448,0.0995953,0.0509885])
C = np.array([0.136649,0.114582,0.100576,0.102412,0.102754,0.104971,0.110123,0.120756])

1 Answers1

2

To assign colors to vertices instead of faces, pcolormesh accepts the parameter shading='gouraud'. Here is an example:

from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(0, 15, 8)
y = np.linspace(0, 10, 5)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)

fig, axs = plt.subplots(ncols=2, figsize=(12, 3))
cmap = 'plasma'
axs[0].scatter(X, Y, s=50, c=Z, cmap=cmap, edgecolors='black')
axs[0].set_title('given vertex colors')
axs[1].pcolormesh(x, y, Z, shading='gouraud', cmap=cmap)
axs[1].scatter(X, Y, s=50, c=Z, cmap=cmap, edgecolors='black')
axs[1].set_title('interpolated vertex colors')
axs[1].set_xlim(axs[0].get_xlim())
axs[1].set_ylim(axs[0].get_ylim())
plt.show()

example plot

JohanC
  • 71,591
  • 8
  • 33
  • 66
  • While this solution helped me in some aspects, I still need a little more help with my own case. The points that I'm going to interpolate don't form a rectangle like this. In my case, areas are divided to elements like in this post: https://stackoverflow.com/questions/62524882/what-is-the-equivalent-of-patch-function-in-matlab-in-python These elements also could be triangles so I think I need a solution that doesn't involve vectors. – Mert Şölen Jun 25 '20 at 10:09
  • Matplotlib as [`tripcolor(...., shading='gouraud')`](https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.tripcolor.html#matplotlib.axes.Axes.tripcolor) to do the same for irregular triangular meshes (quad meshes can easily be transformed to triangular ones). Make sure the `c=colors` has the same number of elements as there are points. If you provide some toy data, it would be easier to show how it fits with your workflow. – JohanC Jun 25 '20 at 10:54
  • I shared a sample data of one element (i.e. one of the rectangles from the post I shared above). There may also be other data types which there are 3, 4 or 6 coordinates depending on the element type. In our case, there are 8 coordinates where 4 of them are on the edges and the other 4 are on the corners. – Mert Şölen Jun 25 '20 at 11:34
  • With your example, you can call `plt.tricontourf(X, Y, C, levels=256)` (default uses the 'viridis' colormap). `tricontourf` interpolates between points (there is no concept of input polygons; internally it connects the points with triangles; you can force holes by adding points with `np.nan` as color value) – JohanC Jun 25 '20 at 12:15
  • This works great with my case, thank you. Is there a way to add shading using tricontourf though? The whole point of having different types of element is to see the interpolation between vertices just like in pcolormesh's gouraud shading. – Mert Şölen Jun 25 '20 at 12:57
  • 1
    Setting `levels=256` has the same effect as gouraud shading. You can choose a colormap with less different colors (default is 'viridis', maybe choose `cmap='inferno'`, for others see [this doc](https://matplotlib.org/3.2.0/tutorials/colors/colormaps.html)) – JohanC Jun 25 '20 at 14:34