Create slice mask in pytorch? - python

Is there a way to specify a mask based on a slice operation?
For example
A = torch.arange(6).view((2,3))
# A = [[0,1,2], [3,4,5]]
mask_slice = torch.mask_slice(A[:,1:])
# mask_slice = [[0,1,1],[0,1,1]]

You can do something like this (if I got your question right):
mask_slice = torch.zeros(A.shape, dtype=bool)
mask_slice[:, 1:] = 1
# tensor([[False, True, True],
# [False, True, True]])

Related

How to apply conditions for rows in a tensor where there is boolean values

I have the following tensor:
predictions = torch.tensor([[ True, False, False],
[False, False, True],
[False, True, True],
[ True, False, False]])
I applied conditions along the axis like below.
new_pred= []
if predictions == ([True,False,False]):
new_pred = torch.Tensor(0)
if predictions == ([False,False,True]):
new_pred = torch.Tensor(2)
if predictions == ([False,True,True]):
new_pred = torch.Tensor(2)
So I want the final output (new_pred) to be:
tensor([0, 2, 2, 0])
But I am getting a blank [] for the new_pred tensor. I think my logic must be flawed since nothing is getting stored in the new_pred. Can someone help me write this logic accurately?
The type of predictions is torch.Tensor while ([True, False, False]) is a list, first, you have to make sure both sides have the same type.
predictions == torch.tensor([True,False,False])
>>> tensor([[ True, True, True],
[False, True, False],
[False, False, False],
[True, True, True]])
Then, you are still comparing a 2d tensor to a 1d tensor, which is ambiguous in an if statement, an easy way to fix this would be to write a for loop, compare each row of the predictions to the conditions and append the result to the new_pred list. Note that you will be comparing two booleans tensors with the size of three, therefore, you have to make sure the result of the comparison is True for all of the cells.
predictions = torch.tensor([[ True, False, False],
[False, False, True],
[False, True, True],
[ True, False, False]])
conditions = torch.tensor([[True,False,False],
[False,False,True],
[False,True,True]])
new_predict = []
for index in range(predictions.size(0)):
if (predictions[index] == conditions[0]).all():
new_predict.append(0)
# ...
Alternatively, you can use slicing to achieve your expected result without any for loop.

Finding unique indices between arrays returned by numpy.where

I have two numpy arrays returned by the function numpy.where, like so:
A = numpy.where(img == 255)
B = numpy.where(img2 != 0)
I need to find number of unique coordinates in A and B. I initially contemplated using numpy.intersect1d to get the number of common indices, and subtract this from the total number of elements from both arrays. But these arrays are not 1-dimensional, so I'm not sure how to go about it.
Any suggestions how I can accomplish this?
Thanks
Numpy interprets the xor operator (^) as a logical xor, obeying:
X|Y|X^Y
0|0| 0
0|1| 1
1|0| 1
1|1| 0
So you can xor the boolean arrays:
(img == 255) ^ (img2 != 0)
An example:
>>> img == 255
array([[False, True, False],
[ True, False, False],
[False, False, False]])
>>> img != 0
array([[ True, True, True],
[ True, True, True],
[ True, True, True]])
>>> (img == 255) ^ (img2 != 0)
array([[False, False, True],
[ True, True, True],
[False, False, True]])
>>> ((img == 255) ^ (img2 != 0)).sum()
5
So there are 5 Trues in img or img2 that aren't in the other array at the same index.
update:
If you want the number of Trues in img or img2 (i.e. the same as the union of two sets of their True coordinates). Then use the logical or instead: |.

Build a list of lists using a loop in Python

I am trying to build long lists of boolean elements to be associated to trace visibility in plotly using the python api.
My input is:
list_true = list( np.ones(3, dtype=bool) )
list_false = list( np.zeros(3, dtype=bool) )
blocks = [1,2,3]
How should I define a loop that builds a list of lists so that the position of list_true blocks varies depending on the value of the index blocks[i]?. The ouput should be:
combination1 = list_true + list_false + list_false
combination2 = list_false + list_true + list_false
combination3 = list_false + list_false + list_true
that is:
combination1 = [
True, True, True,
False, False, False,
False, False, False,
]
combination2 = [
False, False, False,
True, True, True,
False, False, False,
]
combination3 = [
False, False, False,
False, False, False,
True, True, True,
]
import numpy as np
list_true = list(np.ones(3, dtype=bool))
list_false = list(np.zeros(3, dtype=bool))
blocks = [1,2,3]
combination = []
for i in blocks:
sub_combination = [list_false for k in range(3)]
sub_combination[i-1] = list_true
combination.append(sub_combination [0] + sub_combination [1] + sub_combination [2])
print('combination1')
print(combination[0])
print('combination2')
print(combination[1])
print('combination3')
print(combination[2])
If I understand you correctly and combination should be a list of lists (matrix basicly) you can do it like this (to solve it more elegantly I have not seperated the combination variables but made a list of combinations):
import numpy as np
list_true = list(np.ones(3, dtype=bool))
list_false = list(np.zeros(3, dtype=bool))
blocks = [1,2,3]
combination = []
for i in range(len(blocks)):
combination.append([list_true, list_true, list_true])
combination[i][i] = list_false
print(combination)
I found the solution to my issue, which changes with the length of the blocks list (as intended) and flattens the combined (nested) list into the desired result. Thanks to #Odame Prince for the tip.
import numpy as np
list_true = list(np.ones(3, dtype=bool))
list_false = list(np.zeros(3, dtype=bool))
blocks = ['A','B','C','D']
for i in range(len(blocks)):
combo_list = [list_false for k in range(len(blocks))]
combo_list[i] = list_true
flat_list = [item for sublist in combo_list for item in sublist]
print('\nCombination{}: {}'.format(i, flat_list) )
Returns:
Combination0: [True, True, True, False, False, False, False, False, False, False, False, False]
Combination1: [False, False, False, True, True, True, False, False, False, False, False, False]
Combination2: [False, False, False, False, False, False, True, True, True, False, False, False]
Combination3: [False, False, False, False, False, False, False, False, False, True, True, True]
You can also use this shorter version with insert:
list_true = np.ones(3, dtype=bool)
list_false = np.zeros(3, dtype=bool)
blocks = [1, 2, 3]
initial = [np.repeat(list_false, 2) for i in range(3)]
final = [np.insert(initial[b-1], (b-1)*3, list_true) for b in blocks]
You can define a generic function to insert a list at position of N and apply it to your true and false lists. The good thing is that you are not restricted to totally 3 lists as in your example. You can have as many lists as you wish (change user defined total n and use it as an argument of function put_true).
You can also give any list you want to the function. You can decide which one you are interested in (chose L_insert, the true list in your example) and which are those you will just use to fill the blanks (chose L2, the false list in your example).
import numpy as np
list_true = list(np.ones(3, dtype=bool) )
list_false = list(np.zeros(3, dtype=bool) )
blocks = [1,2,3]
# generic function to insert list L_insert among L2s
# which list to be inserted, to which position within how many lists
# can all be defined by user
def insert_list(L_insert, L2):
def insert_at_n(n_insert, n_total):
if n_total == 0:
return []
elif n_insert == 1:
return L_insert + insert_at_n(n_insert-1, n_total-1)
else:
return L2 + insert_at_n(n_insert-1, n_total-1)
return insert_at_n
put_true=insert_list(list_true, list_false)
total = 3 # if you want more false list to be appended, simply change this number
put_true_at_n = lambda n: put_true(n, total)
combination1 = put_true_at_n(1)
combination2 = put_true_at_n(2)
combination3 = put_true_at_n(3)
...
combinationn = put_true_at_n(n)
# an additional benefit is that you can simply apply it to a list of integers
# in order to automatize your work
print([put_true_at_n(n) for n in blocks])

how to add two numpy.array with indices or mask

I have two arrays, like as following.
a=numpy.array((1,2,3,4))
b=numpy.array((1,2,3,4))
I just want to add the first two elements. How can i do it with a mask [True, True, False, False], or indice [0,1]
After addition b=(2, 4,3,4)
It's simply:
b[:2] += a[:2]
Or:
mask = numpy.array((True, True, False, False))
b[mask] += a[mask]

Creating a 2D python array to store data

Looking for a way to store this code in a 2D array in python. I've tried making a 1D array and then turning it into a 2D array but my code is still cumbersome and not working. The gap between 4 and 6 is not a typo. Any help would be greatly appreciated.
recno1inds11 = nonzero(data11[:,1]==no1)[0]
recno2inds11 = nonzero(data11[:,1]==no2)[0]
recno3inds11 = nonzero(data11[:,1]==no3)[0]
recno4inds11 = nonzero(data11[:,1]==no4)[0]
recno6inds11 = nonzero(data11[:,1]==no6)[0]
recno7inds11 = nonzero(data11[:,1]==no7)[0]
recno8inds11 = nonzero(data11[:,1]==no8)[0]
recno9inds11 = nonzero(data11[:,1]==no9)[0]
recno10inds11 = nonzero(data11[:,1]==no10)[0]
recno11inds11 = nonzero(data11[:,1]==no11)[0]
recno12inds11 = nonzero(data11[:,1]==no12)[0]
recno13inds11 = nonzero(data11[:,1]==no13)[0]
recno14inds11 = nonzero(data11[:,1]==no14)[0]
recno15inds11 = nonzero(data11[:,1]==no15)[0]
recno16inds11 = nonzero(data11[:,1]==no16)[0]
recno17inds11 = nonzero(data11[:,1]==no17)[0]
recno18inds11 = nonzero(data11[:,1]==no18)[0]
recno19inds11 = nonzero(data11[:,1]==no19)[0]
recno20inds11 = nonzero(data11[:,1]==no20)[0]
recno21inds11 = nonzero(data11[:,1]==no21)[0]
recno22inds11 = nonzero(data11[:,1]==no22)[0]
recno23inds11 = nonzero(data11[:,1]==no23)[0]
recno24inds11 = nonzero(data11[:,1]==no24)[0]
recno25inds11 = nonzero(data11[:,1]==no25)[0]
recno26inds11 = nonzero(data11[:,1]==no26)[0]
recno27inds11 = nonzero(data11[:,1]==no27)[0]
recno28inds11 = nonzero(data11[:,1]==no28)[0]
recno29inds11 = nonzero(data11[:,1]==no29)[0]
recno30inds11 = nonzero(data11[:,1]==no30)[0]
Normally, you don't want to have 30 separate variables like this, you want to have an array of 30 values.
And if you had that, this would be a one-liner; you could need to transpose the right-hand array into the second axis, then use the == operator.
>>> data11 = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> data11[:,1]
array([2, 5, 8])
>>> no1to5 = np.array([1, 2, 3, 4, 5])
>>> data11[:,1] == no1to5.reshape((5,1))
array([[False, False, False],
[ True, False, False],
[False, False, False],
[False, False, False],
[False, True, False]], dtype=bool)
Of course you can also apply nonzero, grab the first axis, … whatever you want to do, you can vectorize it as long as you have a vector in the first place, instead of a big collection of separate values that are only related by the meta-information in the variable names you happen to have bound them to.

Categories

Resources