1

I wanna slice a 2D numpy array between 3 coordinates, for example, given this numpy,

[[0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]]

and coordinates (1,1) (3,1) (3,5), I want this:

[[0 0 0 0 0 0 0 0]
 [0 1 0 0 0 0 0 0]
 [0 1 1 1 0 0 0 0]
 [0 1 1 1 1 1 0 0]]

any tips and guide are very appreciated.

Ali Abbasi
  • 894
  • 9
  • 22
  • 1
    I think you need to generate all indices (`np.indices`, `np.meshgrid`), and then apply some function that calculates whether a specific pair is within the triangle. The goal will be a boolean mask, or the equivalent `where` coordinates. – hpaulj Mar 28 '18 at 19:53
  • Maybe you'll find this useful: [How do I check if a point is inside a triangle](https://stackoverflow.com/questions/20248076/how-do-i-check-if-a-point-is-inside-a-triangle-on-the-line-is-ok-too). – pault Mar 28 '18 at 20:07
  • It's very likely that [`numpy.tril_indices_from`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.tril_indices_from.html#numpy.tril_indices_from) is what you want. – Mazdak Mar 28 '18 at 20:16
  • @Kasramvd, The `np.tri...` functions expect a square array – hpaulj Mar 28 '18 at 20:19
  • @hpaulj ah! yeah didn't notice that. But It seems that it's still convertible to a lower-triangle problem. Maybe by doing it for a proper slice and them changing the indices respectively. – Mazdak Mar 28 '18 at 20:21

1 Answers1

1

The core function for the np.tri... family of functions is np.tri.

Looking at its code, we see that it does (for a square array):

In [36]: np.greater_equal.outer(np.arange(4),np.arange(+1, 4+1))
Out[36]: 
array([[False, False, False, False],
       [ True, False, False, False],
       [ True,  True, False, False],
       [ True,  True,  True, False]])

Playing around with that I can generate something closer to your example:

In [39]: np.greater_equal.outer(np.arange(4),.5*np.arange(+1, 8+1))
Out[39]: 
array([[False, False, False, False, False, False, False, False],
       [ True,  True, False, False, False, False, False, False],
       [ True,  True,  True,  True, False, False, False, False],
       [ True,  True,  True,  True,  True,  True, False, False]])
In [40]: _.astype(int)
Out[40]: 
array([[0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 0, 0, 0, 0],
       [1, 1, 1, 1, 1, 1, 0, 0]])

Whether this is a useful approach depends on how general of a triangle you want. The example is a variation on the traditional lower triangle. But if the points were more general, say:

 (1,1), (3,2), (2,6)

you'd have to come up with a more sophisticated

hpaulj
  • 221,503
  • 14
  • 230
  • 353