0

I have an array of points that I am plotting in Matplotlib. Here is my code:

masked = r['masks']

  fig=plt.figure()
  ax2=fig.add_axes([0,0,1,1])

  colors = ['b', 'g', 'r', 'c', 'm','y']

  for idx in range(masked.shape[2]):
    array = masked[:,:,idx]

    xs = []
    ys = []
    for i in range(len(array)):
        for j in range(len(array[0])):
            if array[i][j] == True:
                xs.append(j)
                ys.append(i)
    # ys.reverse()

    ax2.scatter(xs, ys, color=str(colors[idx]))
  
  plt.show()

And that gives me this plot: PLOT 1

When I then uncomment the ys.reverse() in the code snippet above, I expect the image to be vertically flipped, but instead I get this, which is completely wrong:

PLOT 2

How can I fix this and make the plot correctly flipped? NOTE: I do not want a solution such as plt.gca.invert_yaxis() - I want the points arrays to be corrected.

Thanks, Vineeth

  • If you wanna flip the image horizontally you need to flip the x-axis right? – Simon Fredrich Aug 09 '20 at 20:24
  • Oh sorry - vertical flip! Just edited the question @SimonFredrich – Vineeth Vejus Aug 09 '20 at 20:28
  • 1
    It’s a scatter plot so reversing y will muck up the data, i.e. you have points (x0, y0) that will become (x0, yn). If you want to _flip_ `y` without just flipping the plot axis you need to do something like `y = y.max() - y`. You can replace `y.max()` with a more appropriate number. – David Hoffman Aug 09 '20 at 20:36
  • Thanks @DavidHoffman, make an answer and I'll mark as accepted. – Vineeth Vejus Aug 09 '20 at 20:55
  • Matplotlib can flip the axis for you: https://stackoverflow.com/a/8280500/1011724 – Dan Aug 09 '20 at 21:55
  • Does this answer your question? [Reverse Y-Axis in PyPlot](https://stackoverflow.com/questions/2051744/reverse-y-axis-in-pyplot) – Dan Aug 09 '20 at 21:55
  • No @Dan, as I mentioned in the question, I do not want a solution that flips the axis. – Vineeth Vejus Aug 09 '20 at 23:10

2 Answers2

0

It’s a scatter plot so reversing ys will muck up the data, i.e. you have points (x0, y0) that will become (x0, yn).

If you want to flip ys without just flipping the plot axis you need to do something like ys = (ys.max() + ys.min()) - ys. You can replace (ys.max() + ys.min()) with a more appropriate number.

In your code you'd replace:

ax2.scatter(xs, ys, color=str(colors[idx]))

With:

xs = np.asarray(xs)
ys = np.asarray(ys)

# reverse ys
ys = (ys.max() + ys.min()) - ys

ax2.scatter(xs, ys, color=str(colors[idx]))
David Hoffman
  • 2,205
  • 1
  • 16
  • 30
-1

When you do a scatter plot what matplotlib does is take the nth element of the x and y arrays and use those coordinates to draw a point. This is why just reversing the order doesn't work (at least I haven't found a working solution that way). What you should do instead is transform the points correctly - warning, some linear algebra ahead! The idea is simple:

  • First subtract the xs mean to every xs point (its mean will then be zero)
  • Then, transform the xs and ys points with a horizontal flipping matrix [[-1, 0], [0, 1]]
  • Finally, add the xs mean back, so the points are again x-centered where they were before

So after creating the arrays you should try the following:

xs_mean = sum(xs) / len(xs)
matrix = [[-1, 0], [0, 1]]

xss, yss = [], []
for x, y in zip(xss, yss):
    [x, y] = np.matmul(matrix, [x, y])
    xss.append(x + x_mean)
    yss.append(y)

ax2.scatter(xss, yss, color=str(colors[idx]))

I am sure there is might be a simpler way to do this, but I hope this proves useful