Matplotlib箭头图:参数顺序

huangapple go评论95阅读模式
英文:

Matploltib quiver plot: argument order

问题

给定一个二维数组,其中包含方位值(如由高程模型的方位导数表示的罗盘方位),我正在使用matplotlib创建一个箭头图。这个箭头图被放置在一个彩色的方位值矩阵上,以充当检查。


问题: 尽管matplotlib.pyplot.quiver()期望的参数顺序是quiver([X, Y], U, V, [C], **kw),但为什么我的代码只在使用quiver([X, Y], V, U)(即U和V的顺序相反)时才得到预期的答案?


顺便说一下,在绘图时,我已将plt.imshow的原点移动到lower(如这里所讨论)。我认为问题与我的索引等相关。

以下是Python 3.5和matplotlib v3.x的代码:

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. def compassBearing_to_standardPosition__degrees_counterClockwise(bearing_deg):
  4. """Vector magnitude and direction calculations assume angle is relative to the x axis
  5. i.e. 0 degrees north is at 3 o'clock
  6. Adjust compass bearings to be relative to standard position
  7. """
  8. std_pos = (450 - bearing_deg) % 360
  9. return std_pos
  10. def calculate_U_and_V__vector_magnitude_and_direction(angle_degrees, magnitude=1):
  11. """Calculates the components of a vector given in magnitude (U) and direction (V) form
  12. angle: Expected that angles are in standard position
  13. i.e. relative to the x axis or where 3 o'clock is zero and not the compass bearing
  14. where 12 o'clock is 0
  15. magnitude: defaults to 1
  16. """
  17. angle_rad = np.deg2rad(angle_degrees)
  18. x = magnitude * np.cos(angle_rad) # change in x == U
  19. y = magnitude * np.sin(angle_rad) # change in y == V
  20. return x, y
  21. def array_indices(arr, indexing='xy'):
  22. """Calculates index positions of each cell in array
  23. These can be used to map to e.g. when creating a quiver plot
  24. indexing: Giving the string 'ij' returns a meshgrid with
  25. matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing.
  26. In the 2-D case with inputs of length M and N, the outputs are of shape
  27. (N, M) for 'xy' indexing and (M, N) for 'ij' indexing.
  28. """
  29. nrows, ncols = arr.shape
  30. nx = 1
  31. ny = 1
  32. x = np.linspace(0, ncols-1, ncols)
  33. y = np.linspace(0, nrows-1, nrows)
  34. xi, yi = np.meshgrid(x, y, indexing=indexing)
  35. return xi, yi
  36. # 创建一个方位角度网格(北方为0度)
  37. aspect_grid = np.array([[216, 226, 151],
  38. [74, 323, 268],
  39. [177, 204, 84]])
  40. # 获取数组索引
  41. x, y = array_indices(aspect_grid, indexing='xy')
  42. # 获取U和V
  43. x_change, y_change = calculate_U_and_V__vector_magnitude_and_direction(aspect_grid.flatten())
  44. # 在imshow上绘制quiver
  45. cmap = 'twilight_shifted' # 这需要matplotlib v3.x
  46. plt.imshow(np.floor(aspect_grid), cmap=cmap, origin='lower')
  47. plt.colorbar(label="Aspect (degrees N)")
  48. plt.quiver(x, y, y_change, x_change, pivot='middle') # <<< 为什么不是x、y、x_change、y_change?
  49. plt.title("Surface aspect values")
  50. plt.show()
英文:

Given a 2D array of aspect values (compass bearings e.g. as represented by the aspect derivative of an elevation model), I'm creating a quiver plot using matplotlib. This is being placed over a coloured matrix of the aspect values to act as a check.

The code is working in that it creates what I want but only where the arguments are opposite to what I expect. I'm making a simple mistake but can't spot it.


QUESTION: Although matplotlib.pyplot.quiver() expects quiver([X, Y], U, V, [C], **kw), why does my code only give the expected answer where quiver([X, Y], V, U) (i.e. U and V are the other way around) is used?


Incidentally, when plotting, I've shifted the origin of plt.imshow to lower (as discussed here). I think the problem lies somewhere related to my indexing etc.

Code below (using python 3.5 and matplotlib v3.x):

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. def compassBearing_to_standardPosition__degrees_counterClockwise(bearing_deg):
  4. &quot;&quot;&quot;Vector magnitude and direction calculations assume angle is relative to the x axis
  5. i.e. 0 degrees north is at 3 o&#39;clock
  6. Adjust compass bearings to be relative to standard position
  7. &quot;&quot;&quot;
  8. std_pos=(450 - bearing_deg) % 360
  9. return(std_pos)
  10. def calculate_U_and_V__vector_magnitude_and_direction(angle_degrees, magnitude=1):
  11. &quot;&quot;&quot;Calculates the components of a vector given in magnitude (U) and direction (V) form
  12. angle: Expected that angles are in standard position
  13. i.e. relative to the x axis or where 3 o&#39;clock is zero and not the compass bearing
  14. where 12 o&#39;clock is 0
  15. magnitude: defaults to 1
  16. &quot;&quot;&quot;
  17. angle_rad=np.deg2rad(angle_degrees)
  18. x = magnitude * np.cos(angle_rad) # change in x == U
  19. y = magnitude * np.sin(angle_rad) # change in y == V
  20. return(x,y)
  21. def array_indices(arr, indexing=&#39;xy&#39;):
  22. &quot;&quot;&quot;Calculates index positions of each cell in array
  23. These can be used to map to e.g. when creating a quiver plot
  24. indexing: Giving the string &#39;ij&#39; returns a meshgrid with
  25. matrix indexing, while &#39;xy&#39; returns a meshgrid with Cartesian indexing.
  26. In the 2-D case with inputs of length M and N, the outputs are of shape
  27. (N, M) for &#39;xy&#39; indexing and (M, N) for &#39;ij&#39; indexing.
  28. &quot;&quot;&quot;
  29. nrows, ncols = arr.shape
  30. nx = 1
  31. ny = 1
  32. x = np.linspace(0, ncols-1, ncols)
  33. y = np.linspace(0, nrows-1, nrows)
  34. #y = np.linspace(nrows-1, 0, nrows) # note that the largest vlue is first
  35. xi, yi = np.meshgrid(x, y, indexing=indexing)
  36. return(xi, yi)
  37. #Create a toy aspect grid (degrees North)
  38. aspect_grid=np.array([[ 216, 226, 151],
  39. [ 74, 323, 268],
  40. [ 177, 204, 84]])
  41. #Get the array indices
  42. x,y=array_indices(aspect_grid, indexing=&#39;xy&#39;)
  43. #Get U and V
  44. x_change,y_change=calculate_U_and_V__vector_magnitude_and_direction(aspect_grid.flatten())
  45. #Plot quiver over imshow
  46. cmap = &#39;twilight_shifted&#39; # this will expect matplotlib v3.x
  47. plt.imshow(np.floor(aspect_grid), cmap=cmap, origin=&#39;lower&#39;)
  48. plt.colorbar(label=&quot;Aspect (degrees N)&quot;)
  49. plt.quiver(x, y, y_change, x_change, pivot=&#39;middle&#39;) # &lt;&lt;&lt; why not x,y,x_change,y_change?
  50. plt.title(&quot;Surface aspect values&quot;)
  51. plt.show()

答案1

得分: 1

When you pass your aspect_grid array into calculate_U_and_V__vector_magnitude_and_direction, you aren't converting them from absolute bearing to counterclockwise degrees since compassBearing_to_standardPosition__degrees_counterClockwise is not being called in calculate_U_and_V__vector_magnitude_and_direction. Due to the 90-degree misalignment of the two conventions, this leads cos(angle) to correspond to the y component and sin(angle) to correspond to the x component (due to the property cos(x - pi/2) == sin(x)). In order to correct this, you simply need to use the conversion you have set up (which does correctly convert from bearing to standard position) by doing something like:

  1. #...
  2. angle_degrees = compassBearing_to_standardPosition__degrees_counterClockwise(angle_degrees)
  3. angle_rad = np.deg2rad(angle_degrees)
  4. #...

in calculate_U_and_V__vector_magnitude_and_direction. This will then allow you to use:

  1. plt.quiver(x, y, x_change, y_change, pivot='middle')

and get the correct result.

英文:

When you pass your aspect_grid array into calculate_U_and_V__vector_magnitude_and_direction you aren't converting them from absolute bearing to counterclockwise degrees since compassBearing_to_standardPosition__degrees_counterClockwise is not being called in calculate_U_and_V__vector_magnitude_and_direction. Due to the 90-degree misalignment of the two conventions this leads cos(angle) to correspond to the y component and sin(angle) to correspond to the x component (due to the property cos(x - pi/2) == sin(x)). In order to correct this you simply need to use the conversion you have set up (which does correctly convert from bearing to standard position) by doing something like

  1. #...
  2. angle_degrees = compassBearing_to_standardPosition__degrees_counterClockwise(angle_degrees)
  3. angle_rad=np.deg2rad(angle_degrees)
  4. #...

in calculate_U_and_V__vector_magnitude_and_direction. This will then allow you to use

  1. plt.quiver(x, y, x_change, y_change, pivot=&#39;middle&#39;)

and get the correct result:

Matplotlib箭头图:参数顺序

huangapple
  • 本文由 发表于 2020年1月3日 22:56:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/59580724.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定