Nov.2022 attempt to use PCA to reconstruct observations ?!?¶

This is for the results section. If it doesn't work, then reorganize so that "results" are what are currently presented as qualitative discussion.

In [119]:
from astropy.io import fits as pyfits
import numpy as np

import matplotlib.pyplot as plt
import matplotlib.cm as cm

import copy
from scipy.interpolate import LinearNDInterpolator
from scipy.interpolate import RegularGridInterpolator

plt.style.use('default')
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Helvetica', 'Roboto', 'Verdana', 'Arial']
plt.rcParams['pdf.fonttype'] = 42
plt.rcParams["axes.grid"] = False
plt.rcParams['axes.facecolor'] = 'white'
plt.rcParams['font.size'] = 14

fullcolor = cm.get_cmap('turbo')
In [125]:
CM7v7 = pyfits.open('output/CM7_v7_cube.fits')
CM7v7.info()

# overall output structure:
# primary - I/F hypercube + description of axes
# ext 1 - lat 2D array
# ext 2 - dlon 2D array
# ext 3 - mu (cos(emi)) 2D array
# ext 4 - mu0 (cos(inc)) 2D array
# ext 5 - g_eff 2D array
# ext 6 - table of parameter values for non-spatial dimensions 3-7

print('')
print('')
print('EXT 6: the BinTable --')
print('')
pvals7 = CM7v7[6].data
print(CM7v7[6].columns)

print('cube_dim: ', pvals7['cube_dim'])
print('dim_name: ', pvals7['dim_name'])
print('{:s}: '.format(CM7v7[6].columns[2].name))
for i in range(5):
    print(i, pvals7.field(2)[i])
print('{:s}: '.format(CM7v7[6].columns[3].name), pvals7.field(3))
print('{:s}: '.format(CM7v7[6].columns[4].name), pvals7.field(4))



print('')
print('')
print('')
print('Filename: output/CM7_v6_cube.fits')
CM7v6 = pyfits.open('../scripts_v6/output/CM7_v6_cube.fits')
pvals6 = CM7v6[6].data
print('cube_dim: ', pvals6['cube_dim'])
print('dim_name: ', pvals6['dim_name'])
print('{:s}: '.format(CM7v6[6].columns[2].name))
for i in range(5):
    print(i, pvals6.field(2)[i])
print('{:s}: '.format(CM7v6[6].columns[3].name), pvals6.field(3))
print('{:s}: '.format(CM7v6[6].columns[4].name), pvals6.field(4))

#planet = np.where(CM7[5].data < 1000., np.ones(CM7[5].data.shape), np.zeros(CM7[5].data.shape))


# read in the PCs and m0 for the maps, scale them to the model parameter ranges

pc1 = plt.imread('northPC1-map.png') # pc1.shape = (301, 601)
pc2 = plt.imread('northPC2-map.png') # values are floats from 0 to 1
pc3 = plt.imread('northPC3-map.png')
pc4 = plt.imread('northPC4-map.png')

hst_mu0= plt.imread('northmu0.png')
hst_mu0 = (0.83695452  -   0.38036991) * hmu0 + 0.38036991

# take PC1 as upper cloud opacity, ranges from 1--15 in the cube
pc_tau_haze = 14. * pc1 + 1.

# take PC2 as deep cloud opacity, ranges from 0--100 in the cube
pc_tau_cloud = 100. * pc2

# take PC2 as cloud depth, ranges from 2--6 in the cube
pc_P_cloud = 4. * pc3 + 2.
Filename: output/CM7_v7_cube.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      48   (16, 16, 3, 3, 3, 5, 4)   float64   
  1  LAT           1 ImageHDU         9   (16, 16)   float64   
  2  DLON          1 ImageHDU         9   (16, 16)   float64   
  3  MU            1 ImageHDU         8   (16, 16)   float64   
  4  MU0           1 ImageHDU         8   (16, 16)   float64   
  5  G_EFF         1 ImageHDU         9   (16, 16)   float64   
  6                1 BinTableHDU     19   5R x 5C   [I, 10A, 40A, I, 6D]   


EXT 6: the BinTable --

ColDefs(
    name = 'cube_dim'; format = 'I'
    name = 'dim_name'; format = '10A'
    name = 'dim_comment'; format = '40A'
    name = 'dim_len'; format = 'I'
    name = 'values_float'; format = '6D'; dim = '(6)'
)
cube_dim:  [3 4 5 6 7]
dim_name:  ['CENWAVE' 'r_H' 'tau_H' 'P_W' 'tau_W']
dim_comment: 
0 Filter central wavelength (micron)
1 Upper trop. haze particle radius (micron
2 Upper trop. haze optical depth
3 Deep cloud base pressure (bar)
4 Deep cloud optical depth
dim_len:  [3 3 3 5 4]
values_float:  [[  0.631   0.727   0.75    0.      0.      0.   ]
 [  0.2     0.5     2.      0.      0.      0.   ]
 [  3.     10.     15.      0.      0.      0.   ]
 [  2.      3.      4.      5.      6.      0.   ]
 [  0.      5.     25.    100.      0.      0.   ]]



Filename: output/CM7_v6_cube.fits
cube_dim:  [3 4 5 6 7]
dim_name:  ['CENWAVE' 'P_H' 'tau_H' 'P_W' 'tau_W']
dim_comment: 
0 Filter central wavelength (micron)
1 Upper trop. haze base pressure (bar)
2 Upper trop. haze optical depth
3 Deep cloud base pressure (bar)
4 Deep cloud optical depth
dim_len:  [3 1 3 5 4]
values_float:  [[  0.631   0.727   0.75    0.      0.      0.   ]
 [  0.5     0.      0.      0.      0.      0.   ]
 [  1.      5.     15.      0.      0.      0.   ]
 [  2.      3.      4.      5.      6.      0.   ]
 [  0.      5.     25.    100.      0.      0.   ]]
In [148]:
# reform the SUNBEAR cubes into something that can be interpolated over
#    - https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.RegularGridInterpolator.html#scipy.interpolate.RegularGridInterpolator
# this may be good for sorting in the right order, mu0 is too big to do it manually:
#    - https://numpy.org/doc/stable/reference/generated/numpy.lexsort.html
# no, we sort by a single key, and we can do the sorting using 1-D mu0, so just use argsort:
#    - https://numpy.org/doc/stable/reference/generated/numpy.argsort.html
# may be able to use numpy.ndarray.sort() method to sort array in place:
#    - https://numpy.org/doc/stable/reference/generated/numpy.ndarray.sort.html

x_pcloud = pvals6['values_float'][3,0:pvals6['dim_len'][3]]
x_taucloud = pvals6['values_float'][4,0:pvals6['dim_len'][4]]
x_tauhaze = np.concatenate((pvals6['values_float'][2,0:2], 
                           pvals7['values_float'][2,0:3]))
     #   array([ 1.,  5.,  3., 10., 15.])
x_tauhaze = np.sort(x_tauhaze)
     #   array([ 1.,  3.,  5., 10., 15.])
x_mu0 = CM7v6[4].data.flatten() 

nx_pcloud = x_pcloud.size
nx_taucloud = x_taucloud.size
nx_tauhaze = x_tauhaze.size
nx_mu0 = x_mu0.size 


cube631 = np.zeros((nx_pcloud, nx_taucloud, nx_tauhaze, nx_mu0))
cube727 = np.zeros((nx_pcloud, nx_taucloud, nx_tauhaze, nx_mu0))
cube750 = np.zeros((nx_pcloud, nx_taucloud, nx_tauhaze, nx_mu0))


for i_pcloud in range(nx_pcloud):
    for i_taucloud in range(nx_taucloud):
                           
        for i_tauhaze in range(2):  # 0: tau=1 from v6, then tau=3 from v7
                                    # 1: tau=5 from v6, then tau=10 from v7
            cube631[i_pcloud][i_taucloud][2*i_tauhaze][:] = \
                        CM7v6[0].data[i_taucloud,i_pcloud,i_tauhaze,0,0,:,:].flatten() 
            cube727[i_pcloud][i_taucloud][2*i_tauhaze][:] = \
                        CM7v6[0].data[i_taucloud,i_pcloud,i_tauhaze,0,1,:,:].flatten() 
            cube750[i_pcloud][i_taucloud][2*i_tauhaze][:] = \
                        CM7v6[0].data[i_taucloud,i_pcloud,i_tauhaze,0,2,:,:].flatten() 

            cube631[i_pcloud][i_taucloud][2*i_tauhaze +1][:] = \
                        CM7v7[0].data[i_taucloud,i_pcloud,i_tauhaze,1,0,:,:].flatten() 
            cube727[i_pcloud][i_taucloud][2*i_tauhaze +1][:] = \
                        CM7v7[0].data[i_taucloud,i_pcloud,i_tauhaze,1,1,:,:].flatten() 
            cube750[i_pcloud][i_taucloud][2*i_tauhaze +1][:] = \
                        CM7v7[0].data[i_taucloud,i_pcloud,i_tauhaze,1,2,:,:].flatten() 

        i_tauhaze=2   # tau=15 from v7                
        cube631[i_pcloud][i_taucloud][2*i_tauhaze][:] = \
                        CM7v7[0].data[i_taucloud,i_pcloud,i_tauhaze,1,0,:,:].flatten() 
        cube727[i_pcloud][i_taucloud][2*i_tauhaze][:] = \
                        CM7v7[0].data[i_taucloud,i_pcloud,i_tauhaze,1,1,:,:].flatten() 
        cube750[i_pcloud][i_taucloud][2*i_tauhaze][:] = \
                        CM7v7[0].data[i_taucloud,i_pcloud,i_tauhaze,1,2,:,:].flatten() 
                                      
# ndarray.sort() uses last axis by default
x_mu0.sort(kind='stable')
cube631.sort(kind='stable')
cube727.sort(kind='stable')
cube750.sort(kind='stable')


# clip and nudge identical mu0 values to make interpolator happy.
# we should have output these to more significant digits in the first place.

for i in range(1,256):
    if (x_mu0[i] - x_mu0[i-1] == 0.):
        x_mu0[i] = x_mu0[i] + 0.001/6.

x_mu0 = copy.deepcopy(x_mu0[32:])
cube631 = copy.deepcopy(cube631[:,:,:,32:])
cube727 = copy.deepcopy(cube727[:,:,:,32:])
cube750 = copy.deepcopy(cube750[:,:,:,32:])

    
# set the interpolator for later use    
interp631 = RegularGridInterpolator((x_pcloud, x_taucloud, x_tauhaze, x_mu0), cube631)
interp727 = RegularGridInterpolator((x_pcloud, x_taucloud, x_tauhaze, x_mu0), cube727)
interp750 = RegularGridInterpolator((x_pcloud, x_taucloud, x_tauhaze, x_mu0), cube750)



# _X_ sort x_tauhaze to match the nice cube order
# _X_ sort cube and x_mu0
# __ create 631, 727, 750, cm7 maps by **interpolating** the PC maps
# __ write out

cube631.shape
Out[148]:
(5, 4, 5, 224)
In [193]:
# DO THE INTERPOLATION

# make arrays to store results
simif_631 = np.zeros_like(hst_mu0)
simif_727 = np.zeros_like(hst_mu0)
simif_750 = np.zeros_like(hst_mu0)

# TEST: switch order --- not good, things look inverted
pc_tau_haze = 14. * pc2 + 1.
pc_tau_cloud = 100. * pc1
pc_P_cloud = 4. * pc3 + 2.
pca_imstack = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
pca_data = pca_imstack.reshape(301*601,4)

# TEST: switch order --- not good, 631 is totally inverted
pc_tau_haze = 14. * pc1 + 1.
pc_tau_cloud = 100. * pc3
pc_P_cloud = 4. * pc2 + 2.
pca_imstack = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
pca_data = pca_imstack.reshape(301*601,4)

# TEST: switch order --- totally crazy, limb darkening opposite, relative features off
pc_tau_haze = 14. * pc3 + 1.
pc_tau_cloud = 100. * pc2
pc_P_cloud = 4. * pc1 + 2.
pca_imstack = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
pca_data = pca_imstack.reshape(301*601,4)

# FIRST GUESS --- decent results, but may need to stretch/scale to match output, limb darkening too strong
# stack up the interpreted PCA values for the interpolator to lookup
pc_tau_haze = 14. * pc1 + 1.
pc_tau_cloud = 100. * pc2
pc_P_cloud = 4. * pc3 + 2.
pca_imstack = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
pca_data = pca_imstack.reshape(301*601,4)

# see what happens if we use PCA to control the model parameters
simif_631 = interp631(pca_data).reshape(301,601)
simif_727 = interp727(pca_data).reshape(301,601)
simif_750 = interp750(pca_data).reshape(301,601)

simcm7_6 = simif_631 / simif_727
simcm7_7 = simif_750 / simif_727
In [204]:
# show straight results

fig,ax = plt.subplots(figsize=(12,15), ncols=1, nrows=3, gridspec_kw={'wspace': 0.05, 'hspace': 0.1})


panel = ax[0].imshow(simif_631 / hst_mu0**0.9, cmap='gray')
panel = ax[1].imshow(simif_727 / hst_mu0**0.9, cmap='gray')
panel = ax[2].imshow(simcm7_6 , cmap='turbo')


for j in range(3):
        ax[j].set_xticks([]) #axes.xaxis.set_ticklabels([])
        ax[j].set_yticks([])
        ax[j].set_frame_on(False)

# save to fits so we can interact with numerical values in DS9, IDL
simif_cm7_hdu = pyfits.PrimaryHDU(simcm7_6)
simif_631_hdu = pyfits.ImageHDU(simif_631/ hst_mu0**0.9)
simif_727_hdu = pyfits.ImageHDU(simif_727/ hst_mu0**0.9)
simif_750_hdu = pyfits.ImageHDU(simif_750/ hst_mu0**0.9)

pca_outdata = pyfits.HDUList([simif_cm7_hdu, simif_631_hdu, simif_727_hdu, simif_750_hdu])
pca_outdata[0].header.set('NEXTEND', 3, 'Number of standard extensions')
pca_outdata.writeto('PCA_simobs.fits', overwrite=True)
In [222]:
# try again with a PCA_v2


pc1 = plt.imread('northPC1-map_v2.png') # pc1.shape = (301, 601)
pc2 = plt.imread('northPC2-map_v2.png') # values are floats from 0 to 1
pc3 = plt.imread('northPC3-map_v2.png')

# V2 --- take PC1 as tau_haze, ranges from 1--15 in the cube
pc_tau_haze = 14. * pc1**0.75 + 1.

# V2 --- take PC2 as tau_cloud, ranges from 0--100 in the cube
pc_tau_cloud = 100. * pc2**0.75

# V2 --- take PC3 as REVERSED P_cloud, ranges from 2--6 in the cube
pc_P_cloud = 6. - 4. * pc3


pca_imstack = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
pca_data = pca_imstack.reshape(301*601,4)

# see what happens if we use PCA to control the model parameters
simif_631 = interp631(pca_data).reshape(301,601)
simif_727 = interp727(pca_data).reshape(301,601)
simif_750 = interp750(pca_data).reshape(301,601)

simcm7_6 = simif_631 / simif_727
simcm7_7 = simif_750 / simif_727

fig,ax = plt.subplots(figsize=(12,15), ncols=1, nrows=3, gridspec_kw={'wspace': 0.05, 'hspace': 0.1})


panel = ax[0].imshow(simif_631, cmap='gray')
panel = ax[1].imshow(simif_727, cmap='gray')
panel = ax[2].imshow(simcm7_6 , cmap='turbo')


for j in range(3):
        ax[j].set_xticks([]) #axes.xaxis.set_ticklabels([])
        ax[j].set_yticks([])
        ax[j].set_frame_on(False)
In [227]:
# try again with a PCA_v3 (used cm7, mu0, if631)
### OK USE THIS

pc1 = plt.imread('northPC1-map_v3.png') # pc1.shape = (301, 601)
pc2 = plt.imread('northPC2-map_v3.png') # values are floats from 0 to 1
pc3 = plt.imread('northPC3-map_v3.png')

# V2 --- take PC1 as tau_haze, ranges from 1--15 in the cube
pc_tau_haze = 14. * pc1 + 1.

# V2 --- take PC3 as tau_cloud, ranges from 0--100 in the cube
pc_tau_cloud = 100. * pc3

# V2 --- take PC2 as P_cloud, ranges from 2--6 in the cube (already reversed in IDL tho)
pc_P_cloud = 2. +  4. * pc2

pca_imstack = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
pca_data = pca_imstack.reshape(301*601,4)

# see what happens if we use PCA to control the model parameters
simif_631 = interp631(pca_data).reshape(301,601) / hst_mu0**0.9
simif_727 = (interp727(pca_data).reshape(301,601)) / hst_mu0**0.9
simif_750 = interp750(pca_data).reshape(301,601)

simcm7_6 = simif_631 / simif_727
simcm7_7 = simif_750 / simif_727

fig,ax = plt.subplots(figsize=(12,15), ncols=1, nrows=3, gridspec_kw={'wspace': 0.05, 'hspace': 0.1})


panel = ax[0].imshow(simif_631, cmap='gray')
panel = ax[1].imshow(simif_727, cmap='gray')
panel = ax[2].imshow(simcm7_6**0.2 , cmap='turbo')


for j in range(3):
        ax[j].set_xticks([]) #axes.xaxis.set_ticklabels([])
        ax[j].set_yticks([])
        ax[j].set_frame_on(False)


        

# save to FITS, build final figure in IDL
simif_cm7_hdu = pyfits.PrimaryHDU(simcm7_6)
simif_631_hdu = pyfits.ImageHDU(simif_631)
simif_727_hdu = pyfits.ImageHDU(simif_727)
simif_750_hdu = pyfits.ImageHDU(simif_750)

pca_outdata = pyfits.HDUList([simif_cm7_hdu, simif_631_hdu, simif_727_hdu, simif_750_hdu])
pca_outdata[0].header.set('NEXTEND', 3, 'Number of standard extensions')
pca_outdata.writeto('PCA_simobs_v3.fits', overwrite=True)

        
        
        
# Debugging commands below this, do not run¶

(preserve saved output graphics)

To verify sort above:¶

add these just before sorting the cubes:

x_mu0_orig = copy.deepcopy(x_mu0)            
cube631_orig = copy.deepcopy(cube631)

then run the cell below to get plots

In [149]:
# interpolate the SUBBEAR data to match the PCs

# make arrays to store results
simif_631 = np.zeros_like(hst_mu0)
simif_727 = np.zeros_like(hst_mu0)
simif_750 = np.zeros_like(hst_mu0)

ny_map, nx_map = hst_mu0.shape
# 301 601    #(these are reverse but hopefully will be fixed back when displayed/written out as files)


# THIS WORKS BUT IS SLOW
for ix in range(nx_map):
    for iy in range(ny_map):

        simif_631[iy,ix] = interp631([pc_P_cloud[iy,ix], pc_tau_cloud[iy,ix], 
                                      pc_tau_haze[iy,ix], hst_mu0[iy,ix]])


imgplot = plt.imshow(simif_631)
plt.show()
In [172]:
# DEBUG: setting up to interpolate the SUBBEAR data to match the PCs

# make arrays to store results
simif_631 = np.zeros_like(hst_mu0)
simif_727 = np.zeros_like(hst_mu0)
simif_750 = np.zeros_like(hst_mu0)

ny_map, nx_map = hst_mu0.shape
# 301 601    #(these are reverse but hopefully will be fixed back when displayed/written out as files)


# can we interp whole image at once?
#simif_631[:,:] = interp631([[pc_P_cloud.flatten()], [pc_tau_cloud.flatten()], 
#                                      [pc_tau_haze.flatten()], [hst_mu0.flatten()]])

#tmp = np.ndarray([pc_P_cloud.flatten()], [pc_tau_cloud.flatten()], 
#                                      [pc_tau_haze.flatten()], [hst_mu0.flatten()])
tmp = np.stack((pc_P_cloud, pc_tau_cloud, pc_tau_haze, hst_mu0),axis=2)
tmp2 = tmp.reshape(301*601,4)

print("shape of tmp2: ", tmp2.shape)
#(180901, 4)

fig,ax = plt.subplots(figsize=(12,8), ncols=1, nrows=2, gridspec_kw={'wspace': 0.2})


ax[0].plot(pc_P_cloud.flatten(), 'o-', color=fullcolor(20), label='pc_P_cloud.flatten() natural order')
ax[0].plot(tmp2[:,0], '.-', color=fullcolor(60), label='tmp2[0,:]')

ax[1].plot(tmp2[:,0] - pc_P_cloud.flatten(), 'o-', color=fullcolor(20), label='diff')

ax[0].legend(fontsize=12)
ax[1].legend(fontsize=12)

#imgplot = plt.imshow(simif_631)
#plt.show()

pts = np.array([[2.1, 6.2, 8.3],
                [3.3, 5.2, 7.1]])
print('"pts" from interpolator docs shape:', pts.shape)
# "pts" from interpolator docs shape: (2, 3)


#  simif_631[:,:] = interp631(tmp2)
#  #ValueError: The requested sample points xi have dimension 180901, but this RegularGridInterpolator has dimension 4


#  simif_631[:,:] = interp631(tmp2)
#  ValueError: could not broadcast input array from shape (180901,) into shape (301,601)
    
simif_631 = interp631(tmp2).reshape(301,601)
    
    # yay, this is waaaaaaay faster
    
    
imgplot = plt.imshow(simif_631)
plt.show()

    
shape of tmp2:  (180901, 4)
"pts" from interpolator docs shape: (2, 3)
In [113]:
# plot some array ordering tests
xseq = np.arange(256)

fig,ax = plt.subplots(figsize=(12,8), ncols=1, nrows=2, gridspec_kw={'wspace': 0.2})


ax[0].plot(xseq, x_mu0, 'o-', color=fullcolor(20), label='x_mu0 sorted')
ax[0].plot(xseq, x_mu0_orig, 'o-', color=fullcolor(60), label='x_mu0_orig')

ax[1].plot(xseq, cube631[2,2,1,:], 'o-', color=fullcolor(20), 
           label='cube631[taucloud=15,pcloud=4,tauhaze=3] sorted')
ax[1].plot(xseq, cube631_orig[2,2,1,:], 'o-', color=fullcolor(60), 
           label='cube631_orig[taucloud=15,pcloud=4,tauhaze=3] sorted')



ax[0].legend(fontsize=12)
ax[1].legend(fontsize=12)
Out[113]:
<matplotlib.legend.Legend at 0x7fe12df2c410>

Debugging interoplator¶

There are some identical values within the mu0 array. We should have output these to more significant digits in the first place. Fudge it by nudging a second identical point up by 1/6 the resolution. Fortunately examination of the array shows that there are no 3-in-a-rows, just identical pairs.

Also, start at 32 (all zeros (off-planet) from 0-31).

In [147]:
# debugging interoplator: 
#    error is "ValueError: The points in dimension 3 must be strictly ascending"

xseq = np.arange(256)

fig,ax = plt.subplots(figsize=(12,8), ncols=1, nrows=2, gridspec_kw={'wspace': 0.2})


ax[0].plot(xseq, x_mu0, 'o-', color=fullcolor(20), label='x_mu0 sorted')
ax[0].plot(xseq, np.roll(x_mu0,-1) - x_mu0, 'o-', color=fullcolor(60), label='offset to next value')
ax[1].plot(xseq, x_mu0, 'o-', color=fullcolor(20), label='x_mu0 sorted')
ax[1].plot(xseq, np.roll(x_mu0,-1) - x_mu0, 'o-', color=fullcolor(60), label='offset to next value')

ax[1].set_ylim([-0.0001, 0.002])

ax[0].legend(fontsize=12)
ax[1].legend(fontsize=12)


#for i in range(25,40):
#    print(i, x_mu0[i], x_mu0[i+1] - x_mu0[i])
# 25 0.0 0.0
# 26 0.0 0.0
# 27 0.0 0.0
# 28 0.0 0.0
# 29 0.0 0.0
# 30 0.0 0.0
# 31 0.0 0.01
# 32 0.01 0.028999999999999998
# 33 0.039 0.003999999999999997

for i in range(1,256):
    if (x_mu0[i] - x_mu0[i-1] == 0.):
        x_mu0[i] = x_mu0[i] + 0.001/6.


#for i in range(25,40):
#    print(i, x_mu0[i], x_mu0[i+1] - x_mu0[i])
#45 0.154 0.008000000000000007
#46 0.162 0.0050000000000000044
##47 0.167 0.004999999999999977
#48 0.172 0.0010000000000000009
#49 0.173 0.016000000000000014
#50 0.189 0.010000000000000009
####51 0.199 0.0
####52 0.199 0.00799999999999998 (same)
#53 0.207 0.007000000000000006
#54 0.214 0.013000000000000012
# 
# 150 0.674 0.0050000000000000044
# 151 0.679 0.0030000000000000027  
# 152 0.682 0.0050000000000000044
# 153 0.687 0.0009999999999998899
# 154 0.688 0.0040000000000000036
# 155 0.692 0.0040000000000000036
# 156 0.696 0.0050000000000000044
# 157 0.701 0.0020000000000000018
# 158 0.703 0.0030000000000000027
# 159 0.706 0.0030000000000000027
# 160 0.709 0.0
# 161 0.709 0.0050000000000000044
# 162 0.714 0.0
# 163 0.714 0.0020000000000000018
# 164 0.716 0.0010000000000000009
# 165 0.717 0.016000000000000014
# 166 0.733 0.0030000000000000027
# 167 0.736 0.0
# 168 0.736 0.0010000000000000009
# 169 0.737 0.0010000000000000009
# 



# need to do a "planet" clip because RegularGridInterpolator gives this error
# based on the mu0 off-planet all being identical:
#     ValueError: The points in dimension 3 must be strictly ascending    
#for i in range(30,35):
#    print(i, x_mu0[i])
#30 0.0
#31 0.0
#32 0.089
#33 0.095
#34 0.1
#35 0.102    
x_mu0 = copy.deepcopy(x_mu0[32:])
cube631 = copy.deepcopy(cube631[:,:,:,32:])
#cube727 = copy.deepcopy(cube727[:,:,:,32:])
#cube750 = copy.deepcopy(cube750[:,:,:,32:])

    
# set the interpolator for later use    
interp631 = RegularGridInterpolator((x_pcloud, x_taucloud, x_tauhaze, x_mu0), cube631)
#interp727 = RegularGridInterpolator((x_pcloud, x_taucloud, x_tauhaze, x_mu0), cube727)
#interp750 = RegularGridInterpolator((x_pcloud, x_taucloud, x_tauhaze, x_mu0), cube750)
    

^^^ note: tauhaze and mu0 are not sorted, mu0 is not masked¶