I have such a numpy array:
And I want to shift this array with N so I can get a new array, such that first 4 rows will be the first 4 rows from the beginning array, and the below rows will be the rows from the previous step.
I dont know how to explain it correctly, but look at the example where I shift with 1 (not the whole array, but I would like to do this for the whole array):
And when I shift with 2 (not the whole array, but I would like to do this for the whole array):
And if I shift with 3, I will have 12 zeros in first column, and 3 previous rows ..
And here's the code:
import numpy as np
import numpy
def shift_one(arr):
arrT = arr.transpose()
arrT_shape = arrT.shape[0]
col1 = arrT[:, [0]]
prev1 = numpy.zeros([arrT_shape, 1])
x1 = numpy.vstack([col1, prev1])
col2 = arrT[:, [1]]
prev2 = arrT[:, [0]]
x2 = numpy.vstack([col2, prev2])
col3 = arrT[:, [2]]
prev3 = arrT[:, [1]]
x3 = numpy.vstack([col3, prev3])
col4 = arrT[:, [3]]
prev4 = arrT[:, [2]]
x4 = numpy.vstack([col4, prev4])
col5 = arrT[:, [4]]
prev5 = arrT[:, [3]]
x5 = numpy.vstack([col5, prev5])
# ... and so on, until we have index [23] and [22] and x24
res = numpy.hstack([x1, x2, x3, x4, x5])
return res
def shift_two(arr):
arrT = arr.transpose()
arrT_shape = arrT.shape[0]
new_size = 2 * arrT_shape
col1 = arrT[:, [0]]
prev1 = numpy.zeros([new_size, 1])
x1 = numpy.vstack([col1, prev1])
col22 = arrT[:, [1]]
col21 = arrT[:, [0]]
prev2 = numpy.zeros([arrT_shape, 1])
x2 = numpy.vstack([col22, col21, prev2])
col32 = arrT[:, [2]]
col31 = arrT[:, [1]]
col30 = arrT[:, [0]]
x3 = numpy.vstack([col32, col31, col30])
col42 = arrT[:, [3]]
col41 = arrT[:, [2]]
col40 = arrT[:, [1]]
x4 = numpy.vstack([col42, col41, col40])
col52 = arrT[:, [4]]
col51 = arrT[:, [3]]
col50 = arrT[:, [2]]
x5 = numpy.vstack([col52, col51, col50])
# ... and so on, until we have index [23], [22], [21] and x24
res = numpy.hstack([x1, x2, x3, x4, x5])
return res
arr1 = np.array([[0, 2, 0, 324],
[1, 2, 0,324],
[2, 2, 0, 324],
[3, 2, 0, 324],
[4, 2, 0, 324],
[5, 2, 0, 324],
[6, 2, 0, 324],
[7, 2, 0, 324],
[8, 2, 0, 324],
[9, 2, 0, 324],
[ 10, 2, 0, 324],
[ 11, 2, 0, 324],
[ 12, 2, 0, 324],
[ 13, 2, 0, 324],
[ 14, 2, 0, 324],
[ 15, 2, 0, 324],
[ 16, 2, 0, 324],
[ 17, 2, 0, 324],
[ 18, 2, 0, 324],
[ 19, 2, 0, 324],
[ 20, 2, 0, 324],
[ 21, 2, 0, 324],
[ 22, 2, 0, 324],
[ 23, 2, 0, 324]])
print(arr1)
print('\n\n')
one = shift_one(arr1)
print(one)
print('\n\n')
two = shift_two(arr1)
print(two)
Basically, I have a problem how to write a function, which will shift it with a given N ... I know how to write it step by step as I did, but I have a problem transforming it into something more usable. Thank you.
So again, an example for array with 5 columns (the original array has 24 columns):
Looped
If you want to do this for the general case, you'll can start with a simple loop. If the input array has shape (M, N), the output will be (M * (delay + 1), N).
Stacking is one way to combine arrays. You can minimize the required number of stacks by always doubling the result:
def stagger(a, delay):
m = a.shape[0]
z = 1
d = delay + 1
while z < d:
k = min(d - z, z) # This will only kick in for the last iteration
new = np.concatenate([np.zeros((m * k, z)), a[:m * k, :-z]], axis=1)
a = np.concatenate([a, new], axis=0)
z *= 2
return a
Vectorized
That being said, there is a fully vectorized way to do this using the monster that is np.lib.stride_tricks.asstrided. Imagine an array that is the first row of your original data padded on the left with delay + 1 zeros:
>>> d = delay + 1 # delay = 7
>>> row = np.concatenate([np.zeros(d), a[0]])
>>> row
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 4., 5., 6., 7.,
8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23.])
You can view this array (without copying the data) as a staggered 2D buffer by adding a fake second dimension whose stride is one element shorter than it ought to be:
>>> m, n = a.shape
>>> staggered_row = np.lib.stride_tricks.as_strided(row[d:], shape=(d, n), strides=(-row.strides[0], row.strides[0]))
>>> staggered_row
array([[ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.,
12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23.],
[ 0., 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.,
11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22.],
[ 0., 0., 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.,
10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21.],
[ 0., 0., 0., 0., 1., 2., 3., 4., 5., 6., 7., 8.,
9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20.],
[ 0., 0., 0., 0., 0., 1., 2., 3., 4., 5., 6., 7.,
8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19.],
[ 0., 0., 0., 0., 0., 0., 1., 2., 3., 4., 5., 6.,
7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18.],
[ 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 4., 5.,
6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 4.,
5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]])
Here, the negative stride adds the elements of the zero padding into the array. Keep in mind that this is generally not safe and should be done with extreme care. The output will not be writable by default, because all the rows refer to largely the same memory locations.
Now imagine doing the same thing to your entire array: padding and adding a new dimension that lets you step back into the padding. If you order the dimensions carefully, a reshape of the view will create a new copy that looks exactly how you want in one step. Specifically, starting with shape (M, N), we pad to (D + M, N), create a view that is (D, M, N), and reshape to (D * M, N):
def staggerx(a, delay):
d = delay + 1
m, n = a.shape
padded = np.concatenate([np.zeros((m, d)), a], axis=1)
view = np.lib.stride_tricks.as_strided(padded[:, d:], shape=(d, m, n), strides=(-padded.strides[1], padded.strides[0], padded.strides[1]))
result = view.reshape(-1, n)
return result
A reshape of a crazily strided array will always make a copy because the data is not contiguous by the way.
If the data is not too humongous concatenating a couple of times will work:
>>> x
array([[ 0, 1, 2, 3, 4],
[ 2, 2, 2, 2, 2],
[ 0, 0, 0, 0, 0],
[324, 324, 324, 324, 324]])
>>> np.concatenate([x] + [np.concatenate([np.zeros(x.shape[0]*i).reshape(-1, i), x[: , i:]] ,axis=1) for i in range(1,x.shape[1])], axis=0)
array([[ 0., 1., 2., 3., 4.],
[ 2., 2., 2., 2., 2.],
[ 0., 0., 0., 0., 0.],
[324., 324., 324., 324., 324.],
[ 0., 1., 2., 3., 4.],
[ 0., 2., 2., 2., 2.],
[ 0., 0., 0., 0., 0.],
[ 0., 324., 324., 324., 324.],
[ 0., 0., 2., 3., 4.],
[ 0., 0., 2., 2., 2.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 324., 324., 324.],
[ 0., 0., 0., 3., 4.],
[ 0., 0., 0., 2., 2.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 324., 324.],
[ 0., 0., 0., 0., 4.],
[ 0., 0., 0., 0., 2.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 324.]])
Each time I generate a 4xi matrix of zeros, and take the i+1: columns from the original matrix to generate the next part. Finally, I concatenate all these arrays.
Related
Suppose I have an input matrix of shape (batch_size ,channels ,h ,w)
in this case (1 ,2 ,3 ,3)
[[[[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.]],
[[ 9., 10., 11.],
[12., 13., 14.],
[15., 16., 17.]]]])
to do a convolution with it i unroll it to the shape of
(batch_size ,channels * kernel_size * kernel_size ,out_h * out_w)
which is:
[[[ 0., 1., 3., 4.],
[ 1., 2., 4., 5.],
[ 3., 4., 6., 7.],
[ 4., 5., 7., 8.],
[ 9., 10., 12., 13.],
[10., 11., 13., 14.],
[12., 13., 15., 16.],
[13., 14., 16., 17.]]]
now i want to get the unrolled matrix back to its original form
which looks like this:
# for demonstration only the first and second column of the unrolled matrix
# the output should be the same shape as the initial matrix -> initialized to zeros
# current column -> [ 0., 1., 3., 4., 9., 10., 12., 13.]
[[[[0+0, 0+1, 0],
[0+3, 0+4, 0],
[0 , 0 , 0]],
[[0+9 , 0+10, 0],
[0+12, 0+13, 0],
[0 , 0 , 0]]]]
# for the next column it would be
# current column -> [ 1., 2., 4., 5., 10., 11., 13., 14.]
[[[[0 , 1+1, 0+2],
[3 , 4+4, 0+5],
[0 , 0 , 0 ]],
[[9 , 10+10, 0+11],
[12 , 13+13, 0+14],
[0 , 0 , 0 ]]]])
you basically put your unrolled elements back to its original place and sum the overlapping parts together.
But now to my question:
How could one implement this as fast as possible using numpy and
as less loops as possible. I already just looped through it kernel by kernel but this aproach isnt feasible with larger inputs. I think this could be parallelized quite a bit but my numpy indexing and overall knowledge isnt good enough to figure out a good solution by myself.
thanks for reading and have a nice day :)
With numpy, I expect this can be done using numpy.lib.stride_tricks.as_strided. However, I'd suggest that you look at pytorch, which interoperates easily with numpy and has quite efficient primitives for this operation. In your case, the code would look like:
kernel_size = 2
x = torch.arange(18).reshape(1, 2, 3, 3).to(torch.float32)
unfold = torch.nn.Unfold(kernel_size=kernel_size)
fold = torch.nn.Fold(kernel_size=kernel_size, output_size=(3, 3))
unfolded = unfold(x)
cols = torch.arange(kernel_size ** 2)
for col in range(kernel_size ** 2):
# col = 0
unfolded_masked = torch.where(col == cols, unfolded, torch.tensor(0.0, dtype=torch.float32))
refolded = fold(unfolded_masked)
print(refolded)
tensor([[[[ 0., 1., 0.],
[ 3., 4., 0.],
[ 0., 0., 0.]],
[[ 9., 10., 0.],
[12., 13., 0.],
[ 0., 0., 0.]]]])
tensor([[[[ 0., 1., 2.],
[ 0., 4., 5.],
[ 0., 0., 0.]],
[[ 0., 10., 11.],
[ 0., 13., 14.],
[ 0., 0., 0.]]]])
tensor([[[[ 0., 0., 0.],
[ 3., 4., 0.],
[ 6., 7., 0.]],
[[ 0., 0., 0.],
[12., 13., 0.],
[15., 16., 0.]]]])
tensor([[[[ 0., 0., 0.],
[ 0., 4., 5.],
[ 0., 7., 8.]],
[[ 0., 0., 0.],
[ 0., 13., 14.],
[ 0., 16., 17.]]]])
I'm trying to build a numpy matrix B knowing its first column and the relationships among columns
To be more specific, I have the first column like array([1],[1],[1],[1]) for B , another known matrix A and the relationship is B(t+1)=B(t)+ A(t+1).
Where B(t) indicates the t column of B. Is there any way that I could build the B using matrix calculation without using for loop?
I have tried np.einsum but it seems like it could only do calculation using the known matrix
A=matrix([[1, 2, 3, 4],
[2, 4, 5, 6],
[3, 5, 6, 7],
[4, 6, 5, 4]])
B=matrix([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
Now, I want to fill the columns of B (except the first column).
I expect the final
B =matrix([[ 1., 3., 6., 10.],
[ 1., 5., 10., 16.],
[ 1., 6., 12., 19.],
[ 1., 7., 12., 16.]])
Thank you!
You could build a new matrix by stacking the first row of B and all but the first row of A. Then you can use np.cumsum() to make a cumulative sum:
A=np.matrix([[1, 2, 3, 4],
[2, 4, 5, 6],
[3, 5, 6, 7],
[4, 6, 5, 4]])
B=np.matrix([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
np.cumsum(np.hstack([B[:,:1], A[:,1:]]), axis=1)
Result:
matrix([[ 1., 3., 6., 10.],
[ 1., 5., 10., 16.],
[ 1., 6., 12., 19.],
[ 1., 7., 12., 16.]])
I can't seem to figure out how to implement the Vandermonde Matrix into Multivariate Interpolation. I am able to get the actual matrix, but I don't understand how to get the values (array) c00,c01,c02... . I know that c = V/z, but I feel like I am missing something (perhaps, not division?). I also know that I need to somehow set up a system of equations (the columns of V are each cij).
How do you do this in python?
Here is what I have so far:
import numpy as np
x = [1, 1, 1, 2, 2, 2, 3, 3, 3]
y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
z = [3.2, 4.4, 6.5, 2.5, 4.7, 5.8, 5.1, 3.6, 2.9]
numpy.polynomial.polynomial.polyvander2d(x, y, [2,2])
>>>array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 2., 4., 1., 2., 4., 1., 2., 4.],
[ 1., 3., 9., 1., 3., 9., 1., 3., 9.],
[ 1., 1., 1., 2., 2., 2., 4., 4., 4.],
[ 1., 2., 4., 2., 4., 8., 4., 8., 16.],
[ 1., 3., 9., 2., 6., 18., 4., 12., 36.],
[ 1., 1., 1., 3., 3., 3., 9., 9., 9.],
[ 1., 2., 4., 3., 6., 12., 9., 18., 36.],
[ 1., 3., 9., 3., 9., 27., 9., 27., 81.]])
np.dot(V, c.flat)and numpy.polynomial.polynomial.polyval2d(x, y, c) I think have to be incorporated into this somehow, but I don't know what to do. Please help!
I am supposed to output:
c = V \ z
c =
0.97500
-5.27500
5.95000
-3.92500
19.82500
-21.55000
3.40000
-14.70000
18.50000
Here is the site where I got this example (They used MatLab):
https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/05Interpolation/multi/
Hope this helps!
Given positions x and y:
x = [1, 1, 1, 2, 2, 2, 3, 3, 3]
y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
and function values z:
z = [3.2, 4.4, 6.5, 2.5, 4.7, 5.8, 5.1, 3.6, 2.9]
V will be the Vandermonde matrix:
V = numpy.polynomial.polynomial.polyvander2d(x, y, [2,2])
V = array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 2., 4., 1., 2., 4., 1., 2., 4.],
[ 1., 3., 9., 1., 3., 9., 1., 3., 9.],
[ 1., 1., 1., 2., 2., 2., 4., 4., 4.],
[ 1., 2., 4., 2., 4., 8., 4., 8., 16.],
[ 1., 3., 9., 2., 6., 18., 4., 12., 36.],
[ 1., 1., 1., 3., 3., 3., 9., 9., 9.],
[ 1., 2., 4., 3., 6., 12., 9., 18., 36.],
[ 1., 3., 9., 3., 9., 27., 9., 27., 81.]])
Each row:
a = x[i]
b = y[i]
V[i,:] = [ 1, b, b², a, a*b, a*b², a², a²b, a²b²]
A linear interpolation aims to solve:
$$z = V \cdot c$$
therefore we need to solve:
$$c = V^{-1} z$$
c = np.linalg.solve(V, z)
c now holds the coefficients in the same orders as the Vandermonde matrix does.
You can evaluate it manually:
def poly_eval(x, y, z):
return z[0] + z[1]*y + z[2]*np.power(y,2) + z[3]*x + z[4]*x*y + z[5]*x*np.power(y,2) + z[6]*np.power(x,2) + z[7]*np.power(x,2)*y + z[8]*np.power(x,2)*np.power(y,2)
or use
np.polynomial.polynomial.polyval2d([1,2], [3,4], c)
Out[22]: array([-65.5, -88.4])
I would like to get several values whose i have the coordinates.
My coordinates are given by "Coord" (shape : (3, 3, 2, 3) : X and Y during 3 times and with 2 because of 2 coordinates) and my values are given by "Values" (shape : (3, 3, 3) for 3 times)
In other words, i would like to concatenate values in time with "slices" for each positions...
I dont know how to undertake that...Here there is a little part of the arrays.
import numpy as np
Coord = np.array([[[[ 4., 6., 10.],
[ 1., 3., 7.]],
[[ 3., 5., 9.],
[ 1., 3., 7.]],
[[ 2., 4., 8.],
[ 1., 3., 7.]]],
[[[ 4., 6., 10.],
[ 2., 4., 8.]],
[[ 3., 5., 9.],
[ 2., 4., 8.]],
[[ 2., 4., 8.],
[ 2., 4., 8.]]],
[[[ 4., 6., 10.],
[ 3., 5., 9.]],
[[ 3., 5., 9.],
[ 3., 5., 9.]],
[[ 2., 4., 8.],
[ 3., 5., 9.]]]])
Values = np.array([[[-4.24045246, 0.97551048, -5.78904502],
[-3.24218504, 0.9771782 , -4.79103141],
[-2.24390519, 0.97882129, -3.79298771]],
[[-4.24087775, 1.97719843, -5.79065966],
[-3.24261128, 1.97886271, -4.7926441 ],
[-2.24433235, 1.98050192, -3.79459845]],
[[-4.24129055, 2.97886284, -5.79224713],
[-3.24302502, 2.98052345, -4.79422942],
[-2.24474697, 2.98215901, -3.79618161]]])
EDIT LATER
I try in case of a simplified problem (without time first). I have used a "for loop" but
somes errors seems subsist...do you think it s the best way to treat this problem? because my arrays are important... 400x300x100
Coord3 = np.array([[[ 2, 2.],
[ 0., 1.],
[ 0., 2.]],
[[ 1., 0.],
[ 2., 1.],
[ 1., 2.]],
[[ 2., 0.],
[ 1., 1.],
[ 0., 0.]]])
Coord3 = Coord3.astype(int)
Values2 = np.array([[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]])
b = np.zeros((3,3))
for i in range(Values2.shape[0]):
for j in range(Values2.shape[1]):
b[Coord3[i,j,0], Coord3[i,j,1]] = Values2[i,j]
b
Your second example is relatively easy to do with fancy indexing:
b = np.zeros((3,3), values2.dtype)
b[coord3[..., 0], coord3[..., 1]] = values2
The origial problem is a bit harder to do, but I think this takes care of it:
coord = coord.astype(int)
x_size = coord[..., 0, :].max() + 1
y_size = coord[..., 1, :].max() + 1
# x_size, y_size = coord.max(axis=(0, 1, 3)) + 1
nt = coord.shape[3]
b = np.zeros((x_size, y_size, nt), values.dtype)
b[coord[..., 0, :], coord[..., 1, :], np.arange(nt)] = values
In the package scipy there is the function to define a binary structure (such as a taxicab (2,1) or a chessboard (2,2)).
import numpy
from scipy import ndimage
a = numpy.zeros((6,6), dtype=numpy.int)
a[1:5, 1:5] = 1;a[3,3] = 0 ; a[2,2] = 2
s = ndimage.generate_binary_structure(2,2) # Binary structure
#.... Calculate Sum of
result_array = numpy.zeros_like(a)
What i want is to iterate over all cells of this array with the given structure s. Then i want to append a function to the current cell value indexed in a empty array (example function sum), which uses the values of all cells in the binary structure.
For example:
array([[0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0],
[0, 1, 2, 1, 1, 0],
[0, 1, 1, 0, 1, 0],
[0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]])
# The array a. The value in cell 1,2 is currently one. Given the structure s and an example function such as sum the value in the resulting array (result_array) becomes 7 (or 6 if the current cell value is excluded).
Someone got an idea?
For the particular case of sums, you could use ndimage.convolve:
In [42]: import numpy as np
In [43]: a = np.zeros((6,6), dtype=np.int)
a[1:5, 1:5] = 1;
a[3,3] = 0;
a[2,2] = 2
In [48]: s = ndimage.generate_binary_structure(2,2) # Binary structure
In [49]: ndimage.convolve(a,s)
Out[49]:
array([[1, 2, 3, 3, 2, 1],
[2, 5, 7, 7, 4, 2],
[3, 7, 9, 9, 5, 3],
[3, 7, 9, 9, 5, 3],
[2, 4, 5, 5, 3, 2],
[1, 2, 3, 3, 2, 1]])
For the particular case of products, you could use the fact that log(a*b) = log(a)+log(b) to convert the problem back to one involving sums. For example, if we wanted to "product-convolve" b:
b = a[1:-1, 1:-1]
print(b)
# [[1 1 1 1]
# [1 2 1 1]
# [1 1 0 1]
# [1 1 1 1]]
we could compute:
print(np.exp(ndimage.convolve(np.log(b), s, mode = 'constant')))
# [[ 2. 2. 2. 1.]
# [ 2. 0. 0. 0.]
# [ 2. 0. 0. 0.]
# [ 1. 0. 0. 0.]]
The situation becomes more complicated if b includes negative values:
b[0,1] = -1
print(b)
# [[ 1 -1 1 1]
# [ 1 2 1 1]
# [ 1 1 0 1]
# [ 1 1 1 1]]
but not impossible:
logb = np.log(b.astype('complex'))
real, imag = logb.real, logb.imag
print(np.real_if_close(
np.exp(
sum(j * ndimage.convolve(x, s, mode = 'constant')
for x,j in zip((real, imag),(1,1j))))))
# [[-2. -2. -2. 1.]
# [-2. -0. -0. 0.]
# [ 2. 0. 0. 0.]
# [ 1. 0. 0. 0.]]
It's easier if you use a 2-deep wall of zeroes:
In [11]: a0
Out[11]:
array([[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 2., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 0., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.]])
In [12]: b0 = zeros_like(a0)
In [13]: for i in range(1,len(a0)-1):
....: for j in range(1,len(a0)-1):
....: b0[i,j] = sum(a0[i-1:i+2, j-1:j+2] * s)
This enables you to multiply the two sub-matrices together and sum, as desired. (You could also do something more elaborate here...)
In [14]: b0
Out[14]:
array([[ 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 1., 2., 3., 3., 2., 1., 0.],
[ 0., 2., 5., 7., 7., 4., 2., 0.],
[ 0., 3., 7., 9., 9., 5., 3., 0.],
[ 0., 3., 7., 9., 9., 5., 3., 0.],
[ 0., 2., 4., 5., 5., 3., 2., 0.],
[ 0., 1., 2., 3., 3., 2., 1., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0.]])
In [15]: b0[1:len(b0)-1, 1:len(b0)-1]
Out[15]:
array([[ 1., 2., 3., 3., 2., 1.],
[ 2., 5., 7., 7., 4., 2.],
[ 3., 7., 9., 9., 5., 3.],
[ 3., 7., 9., 9., 5., 3.],
[ 2., 4., 5., 5., 3., 2.],
[ 1., 2., 3., 3., 2., 1.]])