Home > Software engineering >  Numpy mgrid/ arange
Numpy mgrid/ arange

Time:03-09

I have a bunch of arrays around 10,000~ 10000000. each containing coordinates points x,y,z. I have successfully stored those in Numpy array. i have generated maxi and mini using

np.array(np.amin(Vertex_combined[:,:,:],axis=1))
np.array(np.amax(Vertex_combined[:,:,:],axis=1))

these generate 2 ranges

maxs=array([[406.78, 805.73, 345.14],
           [407.57, 805.83, 345.14],
           [407.9 , 805.83, 314.19]])
mins=array([[405.05, 805.52, 314.15],
           [405.84, 805.62, 314.15],
           [406.78, 805.19, 309.75]])

Now I need to generate

np.mgrid[mins[1,0]:maxs[1,0]:0.5, mins[1,1]:maxs[1,1]:0.5].reshape(2,-1).T
array([[405.84, 805.62],
       [406.34, 805.62],
       [406.84, 805.62],
       [407.34, 805.62]])

this works for single array by when i try

np.mgrid[mins[:,0]:maxs[:,0]:0.5, mins[:,1]:maxs[:,1]:0.5].reshape(2,-1).T

doesn't work. Any help or explanation for what I'm doing wrong would be of great help. thank you,

Traceback (most recent call last):
  File "C:\Users\R414065\AppData\Local\Programs\Python\Python38\lib\site-packages\numpy\lib\index_tricks.py", line 164, in __getitem__
    int(math.ceil((kk.stop - start) / (step * 1.0))))
TypeError: only size-1 arrays can be converted to Python scalars

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    np.hstack(np.mgrid[mins[:,0]:maxs[:,0]:0.5, mins[:,2]:maxs[:,2]:0.5].reshape(2,-1).T)
  File "C:\Users\R414065\AppData\Local\Programs\Python\Python38\lib\site-packages\numpy\lib\index_tricks.py", line 194, in __getitem__
    step = key.step
AttributeError: 'tuple' object has no attribute 'step'

CodePudding user response:

As I wrote in the comments, mgrid generates arange (or its equivalent) for each 'dimension'. And that only works with scalar.

But lets look at the ranges that your bounds create:

In [53]: alist=[np.arange(x,y,.5) for x,y in zip(mins[:,0],maxs[:,0])]
In [54]: [x.shape for x in alist]
Out[54]: [(4,), (4,), (3,)]
In [55]: alist=[np.arange(x,y,.5) for x,y in zip(mins[:,1],maxs[:,1])]
In [56]: [x.shape for x in alist]
Out[56]: [(1,), (1,), (2,)]

Any time I see lists of arrays that differ in shape, I think - no way to avoid loops.

If we want the same number of elements for each range we can use linspace:

In [57]: x = np.linspace(mins[:,0],maxs[:,0],4)
In [58]: y = np.linspace(mins[:,1],maxs[:,1],2)
In [59]: x
Out[59]: 
array([[405.05      , 405.84      , 406.78      ],
       [405.62666667, 406.41666667, 407.15333333],
       [406.20333333, 406.99333333, 407.52666667],
       [406.78      , 407.57      , 407.9       ]])
In [60]: y
Out[60]: 
array([[805.52, 805.62, 805.19],
       [805.73, 805.83, 805.83]])

As long as the number of elements in the range is the same, the difference between ranges is just a matter of scaling.

We can generate a mesh from these. It flattens them:

In [71]: I,J=np.meshgrid(x, y, indexing="ij")
In [72]: I.shape
Out[72]: (12, 6)

We could combine the earlier lists into one array:

In [73]: alist
Out[73]: [array([805.52]), array([805.62]), array([805.19, 805.69])]
In [74]: np.hstack(alist)
Out[74]: array([805.52, 805.62, 805.19, 805.69])

But I suspect you want to generate the individual meshes, and combine those, rather than combine the ranges first.

In short, you will need to iterate - unless I'm missing some nuance of what you are seeking.

edit

Here's the full iterative solution - which I think you should have shown, since it clarifies the problem:

Perform the individual mgrid without the reshaping:

In [75]: alist = [
    ...:     np.mgrid[mins[i, 0] : maxs[i, 0] : 0.5, mins[i, 1] : maxs[i, 1] : 0
    ...: .5]
    ...:     for i in range(3)
    ...: ]
In [76]: alist
Out[76]: 
[array([[[405.05],
         [405.55],
         [406.05],
         [406.55]],
 
        [[805.52],
         [805.52],
         [805.52],
         [805.52]]]),
 array([[[405.84],
         [406.34],
         [406.84],
         [407.34]],
 
        [[805.62],
         [805.62],
         [805.62],
         [805.62]]]),
 array([[[406.78, 406.78],
         [407.28, 407.28],
         [407.78, 407.78]],
 
        [[805.19, 805.69],
         [805.19, 805.69],
         [805.19, 805.69]]])]

That highlights how different each grid is. They still differ when reshaped:

In [77]: blist = [x.reshape(2, -1).T for x in alist]
In [78]: blist
Out[78]: 
[array([[405.05, 805.52],
        [405.55, 805.52],
        [406.05, 805.52],
        [406.55, 805.52]]),
 array([[405.84, 805.62],
        [406.34, 805.62],
        [406.84, 805.62],
        [407.34, 805.62]]),
 array([[406.78, 805.19],
        [406.78, 805.69],
        [407.28, 805.19],
        [407.28, 805.69],
        [407.78, 805.19],
        [407.78, 805.69]])]

They could be joined into one (n,2) array:

In [79]: np.vstack(blist)
Out[79]: 
array([[405.05, 805.52],
       [405.55, 805.52],
       [406.05, 805.52],
       [406.55, 805.52],
       [405.84, 805.62],
       [406.34, 805.62],
       [406.84, 805.62],
       [407.34, 805.62],
       [406.78, 805.19],
       [406.78, 805.69],
       [407.28, 805.19],
       [407.28, 805.69],
       [407.78, 805.19],
       [407.78, 805.69]])
  • Related