pythonarraysdictionarysamplingstencils

How to sample a huge 2D array in Python using 2x2 arrays to create a dictionary? (Stencil Algorithm for Python)


I am rather new to programming, so I apologise if this is a classic and trivial question. I have a 100x100 2D array of values which is plotted by means of matplotlib. In this image, each cell has its value (ranging 0.0 to 1.0) and ID (ranging 0 to 9999 starting from the upper left corner). I want to sample the matrix by using a 2x2 moving window which produces two dictionaries:

In the example below (upper left panel), where N has ID=0, the 1st dictionary would yield {'0': (0,1,100,101)} since the cells are numbered 0 to 99 toward the right hand side and 0 to 9900, step=100, downward. The 2nd dictionary would yield {'0': 0.775}, as 0.775 is the average value of the 4 neighboring cells of N. Of course, these dictionaries must have as many keys as "intersections" I have on the 2D array.

How can this be accomplished? And are dictionaries the best "tool" in this case? Thank you guys!

enter image description here

PS: I tried my own way but my code is incomplete, wrong, and I cannot get my head around it:

a=... #The 2D array which contains the cell values ranging 0.0 to 1.0
neigh=numpy.zeros(4)
mean_neigh=numpy.zeros(10000/4)
for k in range(len(neigh)):
    for i in a.shape[0]:
        for j in a.shape[1]:
            neigh[k]=a[i][j]
            ...

Solution

  • Well, dictionaries may in fact be the way in your case.

    Are you sure that the numpy.array format you're using is correct? I don't find any array((int, int)) form in the API. anyway...

    What to do once you have your 2D array declared

    To make things ordered, let's make two functions that will work with any square 2D array, returning the two dictionaries that you need:

    #this is the one that returns the first dictionary
    def dictionarize1(array):
        dict1 = {}
        count = 0
        for x in range(len(array[0]) - 1) :
            for y in range(len(array[0]) - 1):
                dict1[count] = [array[x][y], array[x][y+1], array[x+1][y], array[x + 1][y+1]]
                count = count + 1
        return dict1
    
    def dictionarize2(array):
        dict2 = {}
        counter = 0
        for a in range(len(array[0]) - 1) :
            for b in range(len(array[0]) - 1):
                dict2[counter] = (array[a][b] + array[a][b+1] + array[a+1][b] + array[a + 1][b+1])/4
                counter = counter + 1
        return dict2
    
    #here's a little trial code to see them working
    
    eighties = [[2.0, 2.2, 2.6, 5.7, 4.7], [2.1, 2.3, 2.3, 5.8, 1.6], [2.0, 2.2, 2.6, 5.7, 4.7],[2.0, 2.2, 2.6, 5.7, 4.7],[2.0, 2.2, 2.6, 5.7, 4.7]]
    print("Dictionarize1: \n")
    print(dictionarize1(eighties))
    print("\n\n")
    print("Dictionarize2: \n")
    print(dictionarize2(eighties))
    print("\n\n")
    

    Compared to the first code, i prefered using an integer as a key cause python will print the dictionary sorted in that case (dictionaries are by definition unsorted, but if they have int keys Python will print them out sorted by key). However, you can change it back to a string just using str(count) as I did before.

    I hope this will help, now I'm not very practical with math libraries, but the code that I wrote should work well with any 2D square array that you may want to put as an input!