Search multiple 1D numpy-arrays in 3D numpy-array - python

I got a stl-file from a surface scan. From that I got a 3D-array for every triangles with its 3 points and theire x,y,z coordinates.
Now to find all triangles that have 2 points in common with another 2D array with x,y,z coordinates of points (could also be a list, the format would not be that important).
The example data for my 3D-array would be
Triangle= np.array([[[0, 1, 1],
[1, 0, 1],
[1, 1, 2]],
[[0, 0, 1],
[1, 0, 1],
[0, 1, 1]],
[[3, 0, 1],
[3, 1, 1],
[2, 0, 2]],
[[2, 0, 2],
[3, 1, 1],
[2, 1, 2]],
[[1, 1, 2],
[1, 0, 1],
[2, 0, 2]],
[[2, 0, 2],
[2, 1, 2],
[1, 1, 2]],
[[1, 2, 3],
[0, 1, 1],
[1, 1, 2]],
[[1, 2, 3],
[0, 2, 1],
[0, 1, 1]],
[[0, 3, 1],
[0, 2, 1],
[1, 3, 2]],
[[0, 2, 1],
[1, 2, 3],
[1, 3, 2]],
[[1, 1, 2],
[2, 1, 2],
[2, 2, 1]],
[[2, 2, 1],
[1, 2, 3],
[1, 1, 2]],
[[2, 1, 2],
[3, 1, 1],
[2, 2, 1]],
[[3, 1, 1],
[3, 2, 1],
[2, 2, 1]],
[[2, 3, 1],
[3, 2, 1],
[3, 3, 1]],
[[2, 3, 1],
[2, 2, 1],
[3, 2, 1]],
[[2, 3, 1],
[1, 3, 2],
[1, 2, 3]],
[[1, 2, 3],
[2, 2, 1],
[2, 3, 1]]])
and for the points
points = np.array([[1, 2, 3],
[0, 1, 1],
[0, 2, 1],
[1, 1, 2],
[1, 3, 2],
[2, 2, 1],
[2, 3, 1]])

Let's try broadcasting to compare all the triangle to all the points:
compare = (Triangle[:,:,None,:] == points[None,None,...])
# `all` check if all the coordinates to be equal,
# `sum` counts the equal points
mask = compare.all(axis=-1).sum(axis=(-2,-1)) >=2
Triangle[mask]
Output:
array([[[0, 1, 1],
[1, 0, 1],
[1, 1, 2]],
[[1, 2, 3],
[0, 1, 1],
[1, 1, 2]],
[[1, 2, 3],
[0, 2, 1],
[0, 1, 1]],
[[0, 3, 1],
[0, 2, 1],
[1, 3, 2]],
[[0, 2, 1],
[1, 2, 3],
[1, 3, 2]],
[[1, 1, 2],
[2, 1, 2],
[2, 2, 1]],
[[2, 2, 1],
[1, 2, 3],
[1, 1, 2]],
[[2, 3, 1],
[2, 2, 1],
[3, 2, 1]],
[[2, 3, 1],
[1, 3, 2],
[1, 2, 3]],
[[1, 2, 3],
[2, 2, 1],
[2, 3, 1]]])

Related

How to process a 2D array such that if an element is repeated more than N times, next occurrences of said element fallback to the 2nd column

I need to make a system such that if the number of Category_Number is above the maximum, the number switches to the second column, and so on.
For example, imagine I have this array of 'club choices', where each row is a submission, with first, second, and third choices:
array([first_choice, second_choice, third_choice])
And to track the applicants, we add a tracking number id:
array([(first_choice, id), (second_choice, id), (third_choice, id)], dtype=[('choice', np.int8),('id', np.int16)])
For simplicity's sake, we won't look at the ids for now. I want the 2nd/third choice of a former applicant to tally to the max before the first choices of the next applicants.
arr['choice']:
array([
[3, 1, 2],
[0, 3, 2],
[2, 1, 3],
[3, 2, 1],
[3, 1, 2],
[2, 3, 1],
[0, 1, 2],
[3, 1, 0],
[2, 0, 3],
[2, 1, 0],
[2, 3, 0],
[0, 1, 2],
[0, 1, 2],
[0, 2, 3],
[0, 3, 1],
[0, 3, 2],
[2, 1, 3],
[3, 1, 2],
[1, 0, 3],
[0, 1, 3],
[3, 1, 0],
[0, 2, 3],
[3, 2, 0],
[0, 2, 3],
[2, 1, 0]
])
Now, I want to categorize the data such that if the amount of a particular club type is beyond a number, let's say, 7, then that application's value is switched to the second column, like so:
array([
[3, 1, 2],
[0, 3, 2],
[2, 1, 3],
[3, 2, 1],
[3, 1, 2],
[2, 3, 1],
[0, 1, 2],
[3, 1, 0],
[2, 0, 3],
[2, 1, 0],
[2, 3, 0],
[0, 1, 2],
[0, 1, 2],
[0, 2, 3],
[0, 3, 1],
[0, 3, 2],
#Category 0 max
[2, 1, 3],
[3, 1, 2],
[1, 0, 3],
[1, 3], #was [0, 1, 3]
[3, 1, 0],
[2, 3], #was [0, 2, 3],
#Category 2 would have continued, but due to the changes, it now stops here.
[3, 2, 0],
[], #was [0, 2, 3], then became [2, 3], then became [3], but 3 is also full, so it is now empty.
[1, 0] #was [2, 1, 0]
])
The final choices are simply the first column transposed.
I hope what I am attempting to do is understood. I'm not restricted to numpy, if another approach is faster, I'd accept it. I made a couple of attempts at this, but none of them got anywhere. I don't even know where to start.

why list is giving output like this? [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed last year.
i got surprised by the output from the following code
code:
asal_list=list()
sol_list=[]
given_list=[1,3,6,7]
target=7
def calc(given_list,i,sol_list,target):
if i<=len(given_list):
if sum(sol_list)==target:
global asal_list
print(sol_list)
print(asal_list)
asal_list.append(sol_list)
print(asal_list)
elif i<len(given_list):
for k in range(len(given_list)):
sol_list.append(given_list[k])
if sum(sol_list)<=target:
calc(given_list,k,sol_list,target)
sol_list.pop()
else:
sol_list.pop()
calc(given_list,0,sol_list,target)`
Output:
[1, 1, 1, 1, 1, 1, 1]
[]
[[1, 1, 1, 1, 1, 1, 1]]
[1, 1, 1, 1, 3]
[[1, 1, 1, 1, 3]]
[[1, 1, 1, 1, 3], [1, 1, 1, 1, 3]]
[1, 1, 1, 3, 1]
[[1, 1, 1, 3, 1], [1, 1, 1, 3, 1]]
[[1, 1, 1, 3, 1], [1, 1, 1, 3, 1], [1, 1, 1, 3, 1]]
[1, 1, 3, 1, 1]
[[1, 1, 3, 1, 1], [1, 1, 3, 1, 1], [1, 1, 3, 1, 1]]
[[1, 1, 3, 1, 1], [1, 1, 3, 1, 1], [1, 1, 3, 1, 1], [1, 1, 3, 1, 1]]
[1, 3, 1, 1, 1]
[[1, 3, 1, 1, 1], [1, 3, 1, 1, 1], [1, 3, 1, 1, 1], [1, 3, 1, 1, 1]]
[[1, 3, 1, 1, 1], [1, 3, 1, 1, 1], [1, 3, 1, 1, 1], [1, 3, 1, 1, 1], [1, 3, 1, 1, 1]]
[1, 3, 3]
[[1, 3, 3], [1, 3, 3], [1, 3, 3], [1, 3, 3], [1, 3, 3]]
[[1, 3, 3], [1, 3, 3], [1, 3, 3], [1, 3, 3], [1, 3, 3], [1, 3, 3]]
[1, 6]
[[1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6]]
[[1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6]]
[3, 1, 1, 1, 1]
[[3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1]]
[[3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1], [3, 1, 1, 1, 1]]
[3, 1, 3]
[[3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3]]
[[3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3], [3, 1, 3]]
[3, 3, 1]
[[3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1]]
[[3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1], [3, 3, 1]]
[6, 1]
[[6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1]]
[[6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1]]
[7]
[[7], [7], [7], [7], [7], [7], [7], [7], [7], [7], [7]]
[[7], [7], [7], [7], [7], [7], [7], [7], [7], [7], [7], [7]]
After running this code, i am unable to conclude how on earth asal_list has got its value added even before appending, if some body know about this type of behaviour , I hope i can get some help
and i dont understand why on earth the list even after adding keyword global , is not taking values inside
Thank you if you add some clarity to my confusion.
You are getting your result because you are appending a list to asal_list and lists are mutable so instead of appending a new list every time, you append the same list. To get your intended result, you should append a copy of the list like:
sol_list.copy()
The code will become:
asal_list=list()
sol_list=[]
given_list=[1,3,6,7]
target=7
def calc(given_list,i,sol_list,target):
if i<=len(given_list):
if sum(sol_list)==target:
global asal_list
print(sol_list)
print(asal_list)
asal_list.append(sol_list.copy())
print(asal_list)
elif i<len(given_list):
for k in range(len(given_list)):
sol_list.append(given_list[k])
if sum(sol_list)<=target:
calc(given_list,k,sol_list,target)
sol_list.pop()
else:
sol_list.pop()
calc(given_list,0,sol_list,target)`

Create a 4D list from a 3D list

I'm working with lists and something came up, so let's say I have a 3D list and I want to create a 4D list, so every two positions in the inner lists split, here is what I tried
mylist = [[[0, 2, 1], [0, 3, 1], [0, 4, 3, 1], [0, 4, 3, 1], [0, 3, 2, 1], [0, 2, 3, 4, 1]],
[[0, 2, 1], [0, 4, 2, 3, 1], [0, 4, 3, 1], [0, 4, 3, 1], [0, 3, 2, 1], [0, 2, 3, 4, 1]]]
newlist = [mylist[i: i + 2] for i in range(0, len(mylist), 2)]
print(newlist)
newlist = [[[[0, 2, 1], [0, 3, 1], [0, 4, 3, 1], [0, 4, 3, 1], [0, 3, 2, 1], [0, 2, 3, 4, 1]],
[[0, 2, 1], [0, 4, 2, 3, 1], [0, 4, 3, 1], [0, 4, 3, 1], [0, 3, 2, 1], [0, 2, 3, 4, 1]]]]
but I was expecting something like:
newlist = [[[[0, 2, 1], [0, 3, 1]], [[0, 4, 3, 1], [0, 4, 3, 1]], [[0, 3, 2, 1], [0, 2, 3, 4, 1]]],
[[0, 2, 1], [0, 4, 2, 3, 1]], [[0, 4, 3, 1], [0, 4, 3, 1]], [[0, 3, 2, 1], [0, 2, 3, 4, 1]]]]
I believe I'm missing a for in my list comprehension something like:
newlist = [[mylist[j: j + 2] for j in i] for i in range(0, len(my list), 2)]
but I'm having an error and I can't figure it out what is the problem, so any help will appreciated, thank you so much!
Try this:
newlist=[[list(ls) for ls in zip(i[::2], i[1::2])] for i in mylist]
print(newlist)
Output:
[[[[0, 2, 1], [0, 3, 1]],
[[0, 4, 3, 1], [0, 4, 3, 1]],
[[0, 3, 2, 1], [0, 2, 3, 4, 1]]],
[[[0, 2, 1], [0, 4, 2, 3, 1]],
[[0, 4, 3, 1], [0, 4, 3, 1]],
[[0, 3, 2, 1], [0, 2, 3, 4, 1]]]]
Here is a possible solution. You were very close!
newlist = [[lst[i:i+2] for i in range(0, len(lst), 2)] for lst in mylist]

Removing list of list if any item in list of list is zero

I have a list of list where the sublist contains numbers that are either 0, 1 or 2.
I need to remove any sublist where any of the numbers are 0.
I tried this code:
l = [list(b) for b in x.Branches]
z = 0
list2 = filter(z, l)
print list2
But it keeps telling me that int is not iterable. the first line gets me my list from rhino grasshopper data, and my list is
[[1, 1, 2, 0], [0, 2, 2, 0], [0, 2, 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], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 0], [0, 2, 2, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 0], [0, 2, 2, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 0], [0, 2, 2, 0], [0, 2, 0, 0], [0, 0, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 0], [0, 2, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 0, 2], [2, 0, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 0, 2], [2, 0, 0, 2], [2, 0, 0, 0], [0, 0, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 0, 2], [2, 0, 0, 2], [2, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 2, 2], [2, 2, 2, 2], [2, 2, 0, 2], [2, 0, 0, 2], [2, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 0, 2], [2, 0, 0, 2], [2, 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]]
filter takes function as first argument, I actually got TypeError. That's because 0 is not a function and it is not callable.
In [49]: list(filter(0, l))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-49-fe89c490c585> in <module>
----> 1 list(filter(0, l))
TypeError: 'int' object is not callable
the way I tried is below, hope it helps
In [50]: is_zero = lambda x: x == 0
In [51]: is_all_zero = lambda x: all(map(is_zero, x))
In [52]: not_is_all_zero = lambda x: not is_all_zero(x)
is_zero checks if x is zero
is_all_zero checks if list is all zero
not_is_all_zero get opposite output of is_all_zero
and now we can use not_is_all_zero to filter l
In [54]: list(filter(not_is_all_zero, l))
Out[54]:
[[1, 1, 2, 0],
[0, 2, 2, 0],
[0, 2, 0, 0],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 0],
[0, 2, 2, 0],
[0, 2, 0, 0],
[1, 1, 2, 2],
...
Update
you want filter any of item is zero, so you can apply below function to filter the list
In [55]: is_any_zero = lambda x: any(map(is_zero, x))
In [56]: is_any_zero([0,1])
Out[56]: True
In [57]: is_any_zero([1,1])
Out[57]: False
In [59]: not_is_any_zero = lambda x: not is_any_zero(x)
In [60]: list(filter(not_is_any_zero, l))
Out[60]:
[[1, 1, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[1, 1, 2, 2],
[2, 2, 2, 2]]
To remove lists containing at least one zero, you could use
res = [ls for ls in lst if 0 not in ls]
Here is a hacky way of removing all suslists consisting only of zeros, assuming all elements are non-negative:
res = filter(sum, lst)
This uses the fact that bool(0) == False and bool(x) == True for x > 0.
Another approach to accomplish the same task is this:
list_2 = list(filter(all, l))
Here, the all function evaluates to true if every element being evaluated is true. Since bool(x) is true for all non-zero values, all(l) is true if all values in l are non-zero.

How can i get coordinates point of a skeleton?

I create skeleton images from binary images, like that
I detect end points of that skeletons with mahotas python library but it returns me the full image array with 1 value for end point and zero the others.
I prefer to detect end points' coordinates.
How can i get them?
My Code that compute endpoints:
branch1=np.array([[2, 1, 2], [1, 1, 1], [2, 2, 2]])
branch2=np.array([[1, 2, 1], [2, 1, 2], [1, 2, 1]])
branch3=np.array([[1, 2, 1], [2, 1, 2], [1, 2, 2]])
branch4=np.array([[2, 1, 2], [1, 1, 2], [2, 1, 2]])
branch5=np.array([[1, 2, 2], [2, 1, 2], [1, 2, 1]])
branch6=np.array([[2, 2, 2], [1, 1, 1], [2, 1, 2]])
branch7=np.array([[2, 2, 1], [2, 1, 2], [1, 2, 1]])
branch8=np.array([[2, 1, 2], [2, 1, 1], [2, 1, 2]])
branch9=np.array([[1, 2, 1], [2, 1, 2], [2, 2, 1]])
endpoint1=np.array([[0, 0, 0], [0, 1, 0], [2, 1, 2]])
endpoint2=np.array([[0, 0, 0], [0, 1, 2], [0, 2, 1]])
endpoint3=np.array([[0, 0, 2], [0, 1, 2], [0, 2, 1]])
endpoint4=np.array([[0, 2, 1], [0, 1, 2], [0, 0, 0]])
endpoint5=np.array([[2, 1, 2], [0, 1, 0], [0, 0, 0]])
endpoint6=np.array([[1, 2, 0], [2, 1, 0], [0, 0, 0]])
endpoint7=np.array([[2, 0, 0], [1, 1, 0], [2, 0, 0]])
endpoint8=np.array([[0, 0, 0], [2, 1, 0], [1, 2, 0]])
jpg = 'skel.jpg'
skel = cv2.imread(jpg, 0)
sk = pymorph.binary(skel)
complete_path = 'skel.jpg'
print pymorph.gray(sk).dtype
br1=mah.morph.hitmiss(sk,branch1)
br2=mah.morph.hitmiss(sk,branch2)
br3=mah.morph.hitmiss(sk,branch3)
br4=mah.morph.hitmiss(sk,branch4)
br5=mah.morph.hitmiss(sk,branch5)
br6=mah.morph.hitmiss(sk,branch6)
br7=mah.morph.hitmiss(sk,branch7)
br8=mah.morph.hitmiss(sk,branch8)
br9=mah.morph.hitmiss(sk,branch9)
ep1=mah.morph.hitmiss(sk,endpoint1)
ep2=mah.morph.hitmiss(sk,endpoint2)
ep3=mah.morph.hitmiss(sk,endpoint3)
ep4=mah.morph.hitmiss(sk,endpoint4)
ep5=mah.morph.hitmiss(sk,endpoint5)
ep6=mah.morph.hitmiss(sk,endpoint6)
ep7=mah.morph.hitmiss(sk,endpoint7)
ep8=mah.morph.hitmiss(sk,endpoint8)
br=br1+br2+br3+br4+br5+br6+br7+br8+br9
ep=ep1+ep2+ep3+ep4+ep5+ep6+ep7+ep8
br and ep are the array with all branches and endpoint from i want get coordinates.
So ep should just be a binary numpy array that is 1 only at your endpoint coordinates? In which case you can use either numpy.where or numpy.nonzero to get the indices of the nonzero values in ep:
pseudo_ep = (np.random.rand(512,512) > 0.9)
rows,cols = np.where(pseudo_ep)
These should correspond to the y,x coordinates of your endpoints

Categories