1

I have multiple 2D arrays saved in a list called image_concat. This list will be composed of over a hundred of these arrays, but for now I'm just trying to make my code run for a list with only two of them. These arrays all have different shapes, and I would like to find the largest x-dimension and largest y-dimension out of all the arrays, and then pad all the other ones with enough zeros around the edges so that in the end, they all have the same shape. Note that the largest x-dimension and largest y-dimension might belong to separate arrays, or they might belong to the same one. What I have tried writing so far is not successfully changing the shape of the smaller array for some reason. But I also think that some issues will arise even after changing the shapes, since some arrays might be off by one in the end due to elements in the shape being even or odd.

import astropy
import numpy as np
import math
import matplotlib.pyplot as plt
from astropy.utils.data import download_file
from astropy.io import fits

images = ['http://irsa.ipac.caltech.edu/ibe/data/wise/allsky/4band_p1bm_frm/9a/02729a/148/02729a148-w2-int-1b.fits?center=89.353536,37.643864deg&size=0.6deg', 'http://irsa.ipac.caltech.edu/ibe/data/wise/allsky/4band_p1bm_frm/2a/03652a/123/03652a123-w4-int-1b.fits?center=294.772333,-19.747157deg&size=0.6deg']

image_list = []
for url in images:
    image_list.append(download_file(url, cache=True))

image_concat = [fits.getdata(image) for image in image_list]

# See shapes in the beginning
print(np.shape(image_concat[0]))
print(np.shape(image_concat[1]))

def pad(image_concat):

    # Identify largest x and y dimensions
    xdims, ydims = np.zeros(len(image_concat)), np.zeros(len(image_concat))
    for i in range(len(xdims)):
        x, y = np.shape(image_concat[i])
        xdims[i] = x
        ydims[i] = y
    x_max = int(np.max(xdims))
    y_max = int(np.max(ydims))

    # Pad all arrays except the largest dimensions
    for A in image_concat:
        x_len, y_len = np.shape(A)
        print(math.ceil((y_max-y_len)/2))
        print(math.ceil((x_max-x_len)/2))

        np.pad(A, ((math.ceil((y_max-y_len)/2), math.ceil((y_max-y_len)/2)), (math.ceil((x_max-x_len)/2), math.ceil((x_max-x_len)/2))), 'constant', constant_values=0)

    return image_concat

image_concat = pad(image_concat)

# See shapes afterwards (they haven't changed for some reason)
print(np.shape(image_concat[0]))
print(np.shape(image_concat[1]))

I can't understand why the shape isn't changing for this case. And also, is there a way to easily generalize this so that it will work on many arrays regardless of if they have even or odd dimensions?

curious_cosmo
  • 1,184
  • 1
  • 18
  • 36
  • For the odd shapes, what do you want to do? Add an extra row/column before, or rather after? – nnnmmm Aug 01 '18 at 20:27
  • @nnnmmm Either way -- for now it doesn't make a difference to me as long as they're along the edges – curious_cosmo Aug 01 '18 at 21:10
  • Then maybe do something like `pad_x = (x_max - x_len) // 2`, then call `np.pad` with `(pad_x, x_max - x_len - pad_x)` and similarly for `pad_y`. Note the `//`. This would pad more after for odd `x_max - x_len`. – nnnmmm Aug 01 '18 at 21:26

1 Answers1

3

np.pad doesn't modify the array in-place, it returns a padded array. So you'd need to do image_concat[i] = np.pad(...), where i is the index of A.

nnnmmm
  • 7,964
  • 4
  • 22
  • 41
  • Do I need to loop through `i` as many 1D arrays? I thought it was allowed to pad 2D arrays in one `np.pad` statement. – curious_cosmo Aug 01 '18 at 22:12
  • No, just write `for i in range(len(image_concat)): image_concat[i] = np.pad(...)` – nnnmmm Aug 01 '18 at 22:14
  • @nnnmmm 's suggestion is correct! Changing the 2nd for loop as below might help: `for i in range(len(image_concat)): ...` and `image_concat[i] = np.pad....` – Furkan Dec 23 '21 at 11:51