Given a 4D array that represents a discrete coordinate transformation function such that
arr[x_in, y_in, z_in] = [x_out, y_out, z_out]
I would like to interpolate arr to a grid with more elements (assuming that the samples in arr were initially drawn from a regularly spaced grid of the higher-element cube).
I have tried the RegularGridInterpolator from scipy, however this has been rather slow:
import numpy as np
from scipy.interpolate import RegularGridInterpolator
from time import time
target_size   = 32
reduced_size  = 5
small_shape = (reduced_size,reduced_size,reduced_size,3)
cube_small  = np.random.randint(target_size, size=small_shape, dtype=np.uint8)
igrid = 3*[np.linspace(0, target_size-1, reduced_size)]
large_shape = (target_size, target_size, target_size,3)
cube_large  = np.empty(large_shape)
t0 = time()
interpol = RegularGridInterpolator(igrid, cube_small)
for x in np.arange(target_size):
    for y in np.arange(target_size):
        for z in np.arange(target_size):
            cube_large[x,y,z] = interpol([x,y,z])
print(time()-t0)
Are there any algorithms that come to mind that would be better suited for the task? Maybe there is something that could exploit the fact that in this case, I am only interested in the discrete integer values at each point.
I can't really say for the generation of the grid as I am not totally sure about what you are trying to do. But with respect to just improving the efficiency, using a triple for loop instead of making use of broadcasting is massively slowing down your code
import itertools
import numpy as np
from scipy.interpolate import RegularGridInterpolator
from time import time
target_size   = 32
reduced_size  = 5
small_shape = (reduced_size,reduced_size,reduced_size,3)
cube_small  = np.random.randint(target_size, size=small_shape, dtype=np.uint8)
igrid = 3*[np.linspace(0, target_size-1, reduced_size)]
large_shape = (target_size, target_size, target_size,3)
cube_large  = np.empty(large_shape)
def original_method():
    t0 = time()
    interpol = RegularGridInterpolator(igrid, cube_small)
    for x in np.arange(target_size):
        for y in np.arange(target_size):
            for z in np.arange(target_size):
                cube_large[x,y,z] = interpol([x,y,z])
    print('ORIGINAL METHOD: ', time()-t0)
    return cube_large
def improved_method():
    t1 = time()
    interpol = RegularGridInterpolator(igrid, cube_small)
    arr = np.arange(target_size)
    grid = np.array(list(itertools.product(arr, repeat=3)))
    cube_large = interpol(grid).reshape(target_size, target_size, target_size, 3)
    print('IMPROVED METHOD:', time() - t1)
    return cube_large
c1 = original_method()
c2 = improved_method()
print('Is the result the same?  ', np.all(c1 == c2))
OUTPUT
ORIGINAL METHOD:  6.9040000438690186
IMPROVED METHOD: 0.026999950408935547
Is the result the same?   True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With