how to interpolate missing data within a 3D cube of data, or for a 2D image with missing slices

Hi all,

I am working with a set number 2D images each taken at a different z values (-7 up to +8, steps of 1). I have been able to combine these images into a 3D cube with the z axis being evenly spaced and then used gizmo to view the "surfaces" of the box, no problem.

My problem comes with my second data set, which has missing voltages (was only taken at -7,-5,-3,-1,0,2,4,6,8). I have made this into a 3D cube again, with even spacing again, and have essentially filled in the missing steps with 2D images of NaN values.

My question is: how can I interpolate to fill in this missing data slices?

Currently I am taking a slice in the y,z plane for each given x value, to create a 2D image and am then trying to use Interp2D to fill in the NaN slices but this isn't working (in the second half of the code provided below). This is the image I have attached. How can I interpolate this?
I would then re-populate the 3D cube with the interpolated data.

Thanks in advance for any help!

**********************
Function make_3D_cube()
   
    //make waves to hold the information for the slices and correponding volatges
    string slices="SMP1212_028_kx;temp_neg6;SMP1212_042_kx;temp_neg4;SMP1212_041_kx;temp_neg2;SMP1212_039_kx;SMP1212_037_kx;temp_1;SMP1212_036_kx;temp_3;SMP1212_035_kx;temp_5;SMP1212_034_kx;temp_7;SMP1212_033_kx"
    Make/O voltages={-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8}
 
    String k_scale_str=stringfromlist(0,slices,";")
    wave k_scale = $k_scale_str
   
    //make temp waves to fill in missing voltages with NaN waves
    duplicate/O k_scale, temp_7
    temp_7=nan
    duplicate/O temp_7, temp_neg6, temp_neg4, temp_neg2, temp_1, temp_3, temp_5

    //make 3D cube to poulate
    Make/O/N=(DimSize(k_scale,1), DimSize(k_scale,0), DimSize(voltages,0)) cube_3D
    SetScale/P x, DimOffset(k_scale,1), DimDelta(k_scale,1), "Å^-1", cube_3D
    SetScale/P y, DimOffset(k_scale,0), DimDelta(k_scale,0), "eV", cube_3D
    SetScale/I z, voltages[0], voltages[DimSize(voltages,0)-1], "V", cube_3D
    cube_3D=Nan
   
    //populate 3D cube from 2D slices
    variable v,i,j
    for(v=0;v<DimSize(voltages,0);v+=1) //loop across voltage
        string temp_str=stringfromlist(v,slices,";")
        print temp_str
        wave temp_wv=$temp_str
        for(i=0;i<DimSize(cube_3D,0);i+=1) //loop across k
            for(j=0;j<DimSize(cube_3D,1);j+=1)  // loop across energy          
                cube_3D[i][j][v]=temp_wv[q][p]
            endfor 
        endfor
    endfor
   
    //#########INTERPOLATION SECTION#########-> nb the code works totally fine up to this point
    //interpolate to fill in the missing data slices  
    //for(i=0;i<DimSize(cube_3D,0);i+=1) //loop across k
    for(i=10;i<20;i+=1) //loop across k
        //extract a temp 2D slice in the v,E plane for a given k index
        Make/O/N=(DimSize(cube_3D,2),DimSize(cube_3D,1)) temp_2D
        SetScale/P x, DimOffset(cube_3D,2), DimDelta(cube_3D,2), "Voltage", temp_2D
        SetScale/P y, DimOffset(cube_3D,1), DimDelta(cube_3D,1), "eV", temp_2D
        temp_2D=cube_3D[i][q][p]
        //NewImage/K=0/F temp_2D    //display for debugging purposes   
        //creat a temp wave to write interpolate values to
        duplicate/O temp_2D, interp_temp_2D
        //populate iterpolation wave
        for(v=0;v<DimSize(voltages,0);v+=1) // loop across voltage
            for(j=0;j<DimSize(cube_3D,1);j+=1)  // loop across energy          
                Variable voltage_value, energy_value
                voltage_value=DimOffset(cube_3D, 2)+DimDelta(cube_3D,2)*v //work out voltage (ie z) value, not index
                energy_value=DimOffset(cube_3D, 1)+DimDelta(cube_3D,1)*j // work out energy (ie y) value, not index

                interp_temp_2D=Interp2D(temp_2D, voltage_value, energy_value)                                                           // its this bit that doesn't work

            endfor
        endfor
        //NewImage/K=0/F interp_temp_2D   //display for debugging purposes
    endfor
       
    Killwaves/Z voltages, k_scale, temp_wv, temp_7, temp_neg6, temp_neg4, temp_neg2, temp_1, temp_3, temp_5
End Function
Before you start interpolating your data it may be useful to wonder if interpolation is necessary. If you only want to compare your results graphically, e.g., using Gizmo, you may not even need to interpolate.

If you do determine that you need to interpolate, it seems to me that your example data could be interpolated simply by averaging the two adjacent Voltage columns. Interp2d() is not going to be helpful here because you have NaNs in the immediate neighborhood of each interpolated value. My advice is to use a simple MatrixOP command for every NaN column (say colC) so that:
MatrixOP/O interpolatedCol=0.5*(col(temp_2d,colC-1)+col(temp_2d,colC+1))

If your voltage values are in rows, not columns then replace the col() above with row().

A.G.
WaveMetrics, Inc.