ehpor / hcipy

A framework for performing optical propagation simulations, meant for high contrast imaging, in Python.
https://hcipy.org
MIT License
89 stars 30 forks source link

PyramidWavefrontSensorEstimator.estimate() Attribute Error. Related to warning message? #231

Open crystalskim opened 4 weeks ago

crystalskim commented 4 weeks ago

I am attempting to output dynamic AO images like in this tutorial except using a pyramid WFS. At the last step when outputting the animation video, I keep getting the following error while calculating the image slopes. I see there is a warning message already, but I saw it was added six years ago. Are these issues related? Does the PWFS need a different approach to work?

AttributeError                            Traceback (most recent call last)
Cell In[90], line 23
     20 wfs_image = hcipy.large_poisson(wfs_image).astype('float')
     22 # Calculate slopes from WFS image
---> 23 slopes = pwfse.estimate([wfs_image + 1e-10])
     24 slopes -= slopes_ref
     25 slopes = slopes.ravel()

File ~\AppData\Local\anaconda3\Lib\site-packages\hcipy\wavefront_sensing\pyramid.py:240, in PyramidWavefrontSensorEstimator.estimate(self, images)
    237 import warnings
    238 warnings.warn("This function does not work as expected and will be changed in a future update.", RuntimeWarning)
--> 240 image = images.shaped
    241 sub_shape = image.grid.shape // 2
    243 # Subpupils

AttributeError: 'list' object has no attribute 'shaped'
jsnguyen commented 4 weeks ago

I had the same issue. I'm not sure why the function was marked as broken because the function works fine for a single image instead of list of images.

I instead just copy/pasted the source code and made a new function in my code. The math in that function is correct so it's basically identical. You do need to make your own aperture mask (i.e. a boolean mask that covers the four pupils), however.

def estimate_pwfs_slopes(img, aperture_mask):

    image = img.shaped
    sub_shape = image.grid.shape // 2

    I_a = image[:sub_shape[0], :sub_shape[1]]
    I_b = image[sub_shape[0]:2 * sub_shape[0], :sub_shape[1]]
    I_c = image[sub_shape[0]:2 * sub_shape[0], sub_shape[1]:2 * sub_shape[1]]
    I_d = image[:sub_shape[0], sub_shape[1]:2 * sub_shape[1]]

    norm = I_a + I_b + I_c + I_d
    inv_norm = np.zeros_like(norm)
    inv_norm[norm != 0] = 1 / norm[norm != 0]

    I_x = (I_a + I_b - I_c - I_d) * inv_norm
    I_y = (I_a - I_b - I_c + I_d) * inv_norm

    # I_a bottom left
    # I_b top left
    # I_c top right
    # I_d bottom right

    reshaped_aperture = aperture_mask.shaped[:sub_shape[0], :sub_shape[1]]

    I_x = I_x[reshaped_aperture > 0]
    I_y = I_y[reshaped_aperture > 0]

    return np.array([I_x, I_y])
crystalskim commented 3 weeks ago

Thanks, that got me past the error!