ehpor / hcipy

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

FraunhoferPropagator total power not conserved #228

Closed hyunsooCHOI0215 closed 7 months ago

hyunsooCHOI0215 commented 7 months ago

Hello, hcipy team.

First of all, thanks for your effort for this amazing simulator. I am enjoying it a lot.

However, when I am trying to use FraunhoferPropagator with DM, it seems like the total power is not conserved. However, considering the number of photons (which corresponds to total power) is already determined by the source and not affected by after phase modulation, total energy should be conserved no matter what pattern I put as a phase pattern on the DM.

Can you please check this issue?

Thanks,

Best, Choi.

syhaffert commented 7 months ago

The Fraunhofer propagator should conserve flux. We have many explicit tests for this. Do you have a limited field of view? You can get light loss if the field of view is smaller than the Nyquist limit of the sampling of your pupil. This happens when your aberrations are so strong that light is scattered outside your field of view. So the number of photons in your final image could be different from what you put in. If you don't want this, you need to simulate the full numerical field of view set by your pupil sampling.

hyunsooCHOI0215 commented 7 months ago

Hello Syhaffert,

Can you please check the attached screenshot? On my end, it seems like it is related to the number of pixels that I am modulating.

I used 6464 focal grid with 6464 DM actuator space. and, propagator, I used FraunhoferPropagator as mentioned. (self.propagator_fiber = FraunhoferPropagator(pupil_grid_fiber, focal_grid_fiber, focal_length=focal_length))

image

syhaffert commented 7 months ago

You are applying huge aberrations and a relatively small focal plane. So this looks pretty normal. Could you share the code where you setup the pupil plane and focal plane grids? Also you are setting random pixels on the DM surface. Is that what you are trying to do? Because we generally actuate a DM through its actuators: deformable_mirror.actuators = std * np.random.randn(num_modes)

hyunsooCHOI0215 commented 7 months ago

Hello, The reason for the actuator modulation was to compute the Jacobian matrix of DM influence on the focal plane E-field. Therefore, I tried this by flattening all mirror surfaces and then applying a 1m change to each surface. (dm.surface[ind]=1) However, while working on this, figured out total power is not conserved.

Also, the code for the grids is as follows.

self.num_pupil_pixels_fiber = 64
self D_pupil_fiber = 0.5
self.num_focal_pixels_fiber = 64
D_focus_fiber = 2.1 * 25 * 1e-6

pupil_grid_fiber = make_pupil_grid(self.num_pupil_pixels_fiber, self.D_pupil_fiber)
focal_grid_fiber = make_pupil_grid(self.num_focal_pixels_fiber, D_focus_fiber)

Will this be because applying 1m for each actuator is too huge modulation? Also, what is the maximum height and common action range for the actuator? Tried -1m and 1m and both seem to work and make conjugated modulation but not sure logically -1m makes sense or not...

ehpor commented 7 months ago

+/- 1 meter is way too much to be in the linear regime for an E-field Jacobian. Normally, you'd push by +/- 0.25 waves (= 0.25 * the wavelength of the light) at the very most, but even then you already see non-linearities creep in. We typically use 1nm at 640nm, if we're doing the traditional Jacobian calculation.

And, as Sebastiaan said, power is indeed not conserved going from pupil to focal plane, if the focal plane does not cover the entire field. The power in any part of the focal plane that you are not sampling, is lost and does not count towards photon count.

hyunsooCHOI0215 commented 7 months ago

I see, Yes, it was due to me putting too much modulation on too small area. Thank you all for the help and hope all of you have a great week!