spacetelescope / poppy

Physical Optics Propagation in Python
https://poppy-optics.readthedocs.io
BSD 3-Clause "New" or "Revised" License
210 stars 68 forks source link

Passing wavefronts from one OpticalSystem to another #280

Closed mperrin closed 5 years ago

mperrin commented 5 years ago

This one's tricky. Issue raised by @sdwill:

Right now there is no way to "connect together" multiple optical systems, in the sense of taking an output wavefront from a propagation through one system, and feeding it into a propagation through another system. This could be useful in a variety of contexts including

The complex wavefront output from a given optical system can be obtained using the retain_final parameter to calc_psf. But there is no easy way to hand that in to another system.

Possible enhancements to address this might include one or more of the following alternatives:

Any of the above might have to deal with potential issues of resampling, padding, and other possible inconsistencies of pixel grid sampling between the different stages of calculation.

mperrin commented 5 years ago

Thought about this some more. Possibly the right mental model here is to think of optical systems as linear operators acting on wavefronts. That's true mathematically, but not in how the code here is currently implemented. One could imagine a function on an optical system, maybe call it propagate_through, which takes a wavefront and returns another wavefront:

wave_out = osys.propagate_through(wave_in)

That would make it easy to compose optical systems arbitrarily:

wave_out = osys2.propagate_through(osys1.propagate_through(wave_in))

The current function propagate_mono comes closest to that, but doesn't have exactly the right semantics because it creates a new input wavefront rather than accepting one as a parameter, and it hands back a PSF rather than a wavefront.

If we wanted to do something like the above, in some ways it would be simple to re-cast propagate_mono and calc_psf to sit on top of propagate_through as a lower-level framework. In other ways it might be a hassle. Could be worth some experimentation with test code, potentially.

All this needs further discussion anyway.

mperrin commented 5 years ago

@sdwill and @douglase - I'd appreciate some feedback & thoughts on this one.

FYI I've got a version of the above implemented now, and will be making a PR for comments shortly. It's a moderately substantial refactoring, which pulls out most of the contents of propagate_mono into a new function with a different API as described above. That new function is a linear operator that takes an input complex wavefront and returns an output complex wavefront. This makes it straightforward to arbitrarily chain together propagation calculations.

That new function is tentatively named "propagate_through", but I'm not totally happy with that name. Perhaps just propagate would be better but I worry that could be more confusing than necessary with all the existing propagate_*function names. Name suggestions welcome.

Stand by for the PR soon.