[GIS] Efficient way to store multiple values of an x,y location in Python

imagerypython

I am trying to read values from a stack of images and store them in a structure that will allow for easy readability. My current idea is to create a loop

for x in width:
    for y in length:
        for z in height:

and try appending the z value to a list at [x, y]. The issue with this technique is that I do not know how to prevent losing the x and y position through the iteration and it seems rather inefficient.

The input data will consist of z values extracted from tiff images. I am reading them by first creating a stack through a loop statement

for i, fname in enumerate(image_files):
img = cv2.imread(fname, cv2.CV_LOAD_IMAGE_UNCHANGED)
img_stack[:,:,i] = img

which I found here: https://stackoverflow.com/a/20056062/1342580 (CV2 is only returning nan for me but that's a different question)

After the stack is created I used to loop at the beginning of my question to go through all of the pixels (which at the moment is 3858 x 3742) and append the z value of an x,y location from each image to the x,y value (for example if I had 4 images in the stack the result at position 1, 1 would be [1, 1, Z1, Z2, Z3, Z4]. Then I append that to another list that will contain a list for every x,y position

Is there a better technique for doing this?

Best Answer

I would probably store the values in nested dictionaries, with the keys corresponding to x and y coordinates. The structure would be something like the following for a set of 3x3 images (where all of the x, y and z variables would be replaced with the actual x- and y-coordinates, and corresponding z-values, respectively):

z_stack = {x1:
              {y1: [z11a, z11b, z11c],
               y2: [z12a, z12b, z12c],
               y3: [z13a, z13b, z13c]},
           x2:
              {y1: [z21a, z21b, z21c],
               y2: [z22a, z22b, z22c],
               y3: [z23a, z23b, z23c]},
           x3:
              {y1: [z31a, z31b, z31c],
               y2: [z32a, z32b, z32c],
               y3: [z33a, z33b, z33c]}}

This way, a list of all z-values for coordinates x=3, y=2 (for example), would be returned by z_stack[3][2].

To construct this dictionary, you can use a modified your existing loop like this:

z_stack = {}
for x in width:
    z_stack[x] = {}
    for y in length:
        z_stack[x][y] = []
        for z in height:
            z_stack[x][y].append(z)