could someone give me some ideas of what I can do with this code?
The user will give a number of values as an argument, and the shape will be the dimensions of the list.
The problem here I is with the v variable, I want to use the v variable to index the values(list) so I can change the nth dimension of the list, so for example.
In the example under where i do v+m, I want the index to not start for 0 where i get the value 1 from the value list, but to get the value 5, but I cant find a solution to do this since i need to define v at the start with 0 and check if its not 0.
Any help is appreciated. ps. I dont want to use any numpy arrays or anything other than lists
def test(shape , *values):
n = shape[1]
m = shape[0]
nDim = [[0 for column in range(m)] for row in range(n)]
values = list(values)
for x in range (n):
print(x)
v = 0
if(v%m == 0):
v +=m
for y in range (m):
nDim[x][y] = values[v]
v += 1
return nDim
m = test((4,2) , 1, 2 ,3, 4 , 5 ,6 , 7 , 8)
You are quite close!
It's true you need to set v=0 but you should do that only once, before the first loop, so you won't reset it between loops. And then your modulo condition is not needed at all, as you increment v in every iteration so choose every *values element once.
v = 0
for x in range(n):
for y in range(m):
nDim[x][y] = values[v]
v += 1
You could even omit v as it can be calculated from xand y
nDim[x][y] = values[x * m + y]
I would do it like this:
def to_list_of_lists(shape, *values):
values = list(values)
result = []
for row in range(shape[1]):
start_index = row * shape[0]
stop_index = start_index + shape[0]
result.append(values[start_index:stop_index])
return result
x = to_list_of_lists((4,2) , 1, 2 ,3, 4 , 5 ,6 , 7 , 8)
So I'm trying to get the positions of pixels that surround a pixel :
for example :
0 0 0 0
x x x 0
x 1 x 0
x x x 0
I need to get the positions of all those Xs.
The problem for me isn't the general case I can do a double-loop to get them, the problem is the conditions. Because what came to my mind is to manually code every case, but it isn't efficient and takes too many lines.
Therefore, I'm asking if there is an easier way to do so
I can program it manually by doing several if statement and assign their values to an array
Here is what i wrote for the moment it takes to many lines and isn't efficient
def cond_i_zero(pos_array,i,j):
pos_array[0] = i
pos_array[1] = j-1
pos_array[2] = i
pos_array[3] = j+1
pos_array[4] = i+1
pos_array[5] = j-1
pos_array[6] = i+1
pos_array[7] = j
pos_array[8] = i+1
pos_array[9] = j+1
return pos_array
def cond_j_zero(pos_array,i,j):
pos_array[0] = i-1
pos_array[1] = j
pos_array[2] = i-1
pos_array[3] = j+1
pos_array[4] = i
pos_array[5] = j+1
pos_array[6] = i+1
pos_array[7] = j
pos_array[8] = i+1
pos_array[9] = j+1
return pos_array
"""
i,j : represent the position of the pixel that is equivalent to 1 in the
example above
total_img_nb : 16 for the example
output expected : array of positions so for example since the maximum of pixels that suround a pixel is 8 the output will be an array of size 16
where every pair number represent the i(row) pos and every odd number represent the j (columns) pos
"""
def pos_in_array(total_imgs_nb,i,j):
x = 2
y = 2
size = int(math.sqrt(total_imgs_nb))-1
if ( i == 0 ):
x = 1
if ( j == 0 ):
y = 1
if ( i == size ):
x = size - 1
if ( j == size ):
y = size - 1
pos_array = np.zeros(( total_imgs_nb ))
pos_array += 999
if((i==0 and j == 0) or (i==size and j == size)):
pos_array[0] = i
pos_array[1] = y
pos_array[2] = x
pos_array[3] = j
pos_array[4] = x
pos_array[5] = y
elif (i==0):
pos_array=cond_i_zero(pos_array,i,j)
elif (j==0):
pos_array=cond_j_zero(pos_array,i,j)
elif (i==size):
pos_array[0] = i
pos_array[1] = y
pos_array[2] = x
pos_array[3] = j
pos_array[4] = x
pos_array[5] = y
pos_array[6] = y
pos_array[7] = y
pos_array[8] = y
pos_array[9] = y
else:
count = 0
for w in range(i-1,i+2):
for v in range(j-1,j+2):
pos_array[count] = w
count = count +1
pos_array[count] = v
count = count +1
return pos_array
def main():
pos_array = pos_in_array(16,1,1)
# this usually return
[0. 0. 0. 1. 0. 2. 1. 0. 1. 2. 2. 0. 2. 1. 2. 2.]
Here is how i did it .
first i get the number of neighbours for the pixel
then i create a 1-D array of double the size of the neighbours and then i bound the loop and add the position to the array .
size = int(math.sqrt(nb_total))
if((i==0 and (j ==0 or j==size-1))or (i==size-1 and (j == size -1 or j==0))):
neighbors = 3
elif(i==0 or j==0 or i==size-1 or j==size-1):
neighbors = 5
else:
neighbors = 8
array_pos = np.zeros((neighbors*2))
count = 0
for x in range(size):
for y in range(size):
if(x == i and y == j ):
continue
if((x < i+2 and y <j+2)and (x> i-2 and y > j-2 )):
array_pos[count] = x
count = count + 1
array_pos[count] = y
count = count + 1
if(count == neighbors*2):
break
if(count == neighbors*2):
break
return array_pos
I have the following algo:
Iterate through all rows in 2d-array:
For each processed row I get 1d-array
Replace row i of other 2d-array with processed 1-d array
I'd like to parallelize the process as each row process is independant.
My code:
def update_grid_row(self, grid, new_neighbours_grid, y):
grid_row = np.zeros(GRID_WIDTH + 2)
for x in range(0, GRID_WIDTH):
xy_status = self.get_status_grid(x, y, grid, new_neighbours_grid)
grid_row[x + 1] = xy_status
return grid_row
def get_status_grid(self, x, y, new_grid, new_neighbours_grid):
current_status = new_grid[x + 1][y + 1]
living_neighbours = new_neighbours_grid[x][y]
if living_neighbours < 2 or living_neighbours > 3:
return int(0)
elif current_status == 0 and living_neighbours == 3:
return int(1)
else:
return current_status
def run
original_grid = self.grid
new_grid = original_grid
new_neighbours_grid = self.get_neighbours_grid(new_grid)
for y in range(0, GRID_HEIGHT):
grid_row = self.update_grid_row(original_grid, new_neighbours_grid, y)
new_grid[:, y + 1] = grid_row.T
self.grid = new_grid
Multiprocessing is probably not useful, as pointed out in the comments, but notice that what your neighbor counting corresponds to convolving your grid with the array
1 1 1
1 0 1
1 1 1
So, using scipy.signal.convolve2d will buy you a factor of somewhere 10 and 100.
How can I find the best "match" for small matrix in big matrix?
For example:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
The match is defined as difference of numbers in matrix, so match in position (1,1) is as if number 5 from small would be on number 0 from big matrix (so the central number from small matrix in coordinates (1,1) of big matrix.
The match value in position (1,1) is:
m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+|8−8|+|2−9|=28
The goal is to find the lowest difference posible in those matrixes.
The small matrix always has odd number of lines and columns, so it's easy to find it's centre.
You can iterate through the viable rows and columns and zip the slices of big with small to calculate the sum of differences, and use min to find the minimum among the differences:
from itertools import islice
min(
(
sum(
sum(abs(x - y) for x, y in zip(a, b))
for a, b in zip(
(
islice(r, col, col + len(small[0]))
for r in islice(big, row, row + len(small))
),
small
)
),
(row, col)
)
for row in range(len(big) - len(small) + 1)
for col in range(len(big[0]) - len(small[0]) + 1)
)
or in one line:
min((sum(sum(abs(x - y) for x, y in zip(a, b)) for a, b in zip((islice(r, col, col + len(small[0])) for r in islice(big, row, row + len(small))), small)), (row, col)) for row in range(len(big) - len(small) + 1) for col in range(len(big[0]) - len(small[0]) + 1))
This returns: (24, (1, 0))
Done by hand:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
# collect all the sums
summs= []
# k and j are the offset into big
for k in range(len(big)-len(small)+1):
# add inner list for one row
summs.append([])
for j in range(len(big[0])-len(small[0])+1):
s = 0
for row in range(len(small)):
for col in range(len(small[0])):
s += abs(big[k+row][j+col]-small[row][col])
# add to the inner list
summs[-1].append(s)
print(summs)
Output:
[[28, 29, 38], [24, 31, 39]]
If you are just interested in the coords in the bigger one, store tuples of (rowoffset,coloffset,sum) and dont box lists into lists. You can use min() with a key that way:
summs = []
for k in range(len(big)-len(small)+1):
for j in range(len(big[0])-len(small[0])+1):
s = 0
for row in range(len(small)):
for col in range(len(small[0])):
s += abs(big[k+row][j+col]-small[row][col])
summs .append( (k,j,s) ) # row,col, sum
print ("Min value for bigger matrix at ", min(summs , key=lambda x:x[2]) )
Output:
Min value for bigger matrix at (1, 0, 24)
If you had "draws" this would only return the one with minimal row, col offset.
Another possible solution would be this, returning the minimum difference and the coordinates in the big matrix:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
def difference(small, matrix):
l = len(small)
return sum([abs(small[i][j] - matrix[i][j]) for i in range(l) for j in range(l)])
def getSubmatrices(big, smallLength):
submatrices = []
bigLength = len(big)
step = (bigLength // smallLength) + 1
for i in range(smallLength):
for j in range(step):
tempMatrix = [big[j+k][i:i+smallLength] for k in range(smallLength)]
submatrices.append([i+1,j+1,tempMatrix])
return submatrices
def minDiff(small, big):
submatrices = getSubmatrices(big, len(small))
diffs = [(x,y, difference(small, submatrix)) for x, y, submatrix in submatrices]
minDiff = min(diffs, key=lambda elem: elem[2])
return minDiff
y, x, diff = minDiff(small, big)
print("Minimum difference: ", diff)
print("X = ", x)
print("Y = ", y)
Output:
Minimum difference: 24
X = 1
Y = 2
I would use numpy to help with this.
To start I would convert the arrays to numpy arrays
import numpy as np
small = np.array([[1,2,3], [4,5,6], [7,8,9]])
big = np.array([[2,4,2,3,5], [6,0,1,9,0], [2,8,2,1,0], [7,7,4,2,1]])
then I would initialize an array to store the results of the test (optional: a dictionary as well)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
Then iterate over the positions in which the small matrix can be positioned over the large matrix and calculate the difference:
insert = np.zeros(big.shape)
for i in range(results.shape[0]):
for j in range(results.shape):
insert[i:small.shape[0] + i, j:small.shape[1] + j] = small
results[i, j] = np.sum(np.abs(big - insert)[i:3+i, j:3+j])
# Optional dictionary
result_dict['{}{}'.format(i, j)] = np.sum(np.abs(big - insert)[i:3+i, j:3+j])
Then you can print(results) and obtain:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or because the position of the small matrix over the big matrix is stored in the keys of the dictionary, you can get the position of the small matrix over the large matrix where the difference is smallest by key manipulation:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
and if you print(pos_min), you obtain:
[1, 0]
then if you need the index for anything you can iterate over it if required. Hope this helps!
I am trying to calculate one-step, two-step transition probability matrices for a sequence as shown below :
sample = [1,1,2,2,1,3,2,1,2,3,1,2,3,1,2,3,1,2,1,2]
import numpy as np
def onestep_transition_matrix(transitions):
n = 3 #number of states
M = [[0]*n for _ in range(n)]
for (i,j) in zip(transitions,transitions[1:]):
M[i-1][j-1] += 1
#now convert to probabilities:
for row in M:
s = sum(row)
if s > 0:
row[:] = [f/s for f in row]
return M
one_step_array = np.array(onestep_transition_matrix(sample))
My question, how do we calculate two step transition matrix. because when I manually calculate the matrix it is as below :
two_step_array = array([[1/7,3/7,3/7],
[4/7,2/7,1/7],
[1/4,3/4,0]])
However. np.dot(one_step_array,one_step_arrary) gives me a result which is different and as follows :
array([[0.43080357, 0.23214286, 0.33705357],
[0.43622449, 0.44897959, 0.11479592],
[0.20089286, 0.59821429, 0.20089286]])
Please let me know which one is correct.
You just have to change the transitions index in your for loop:
def twostep_transition_matrix(transitions):
n = 3 #number of states
M = [[0]*n for _ in range(n)]
for (i,j) in zip(transitions,transitions[2:]):
M[i-1][j-1] += 1
#now convert to probabilities:
for row in M:
s = sum(row)
if s > 0:
row[:] = [f/s for f in row]
return M