Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing wavefronts from one OpticalSystem to another #280

Closed
mperrin opened this issue Dec 10, 2018 · 2 comments
Closed

Passing wavefronts from one OpticalSystem to another #280

mperrin opened this issue Dec 10, 2018 · 2 comments
Labels
enhancement New feature or request

Comments

@mperrin
Copy link
Collaborator

mperrin commented Dec 10, 2018

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

  • Building separate, modular optical system models for e.g. telescope and instrument separately, then sticking them together
  • Combining different kinds of propagators, such as a mixed Fraunhofer and Fresnel calculations
  • Running a calculation for a situation in which the starting point is not a simple plane wave as assumed by the existing input_wavefront function.

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:

  • Example code for how to replace input_wavefront with a function that grabs some other existing wavefront as a starting point. Potentially such a function might even run a completely different other system recursively to get its starting wavefront.
  • A container optical system class, notionally CompoundOpticalSystem, which could work similarly to CompoundOpticalElement to iterate over multiple other systems and act to glue them together into something that acts like a larger whole.
  • An ability to directly "add together" OpticalSystem instances, and returns a new optical system instance containing the concatenation of the two sets of optics
  • A new "hybrid" optical system class which allows mixed Fraunhofer & Fresnel propagations?

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 mperrin added the enhancement New feature or request label Dec 10, 2018
@mperrin
Copy link
Collaborator Author

mperrin commented Dec 11, 2018

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
Copy link
Collaborator Author

mperrin commented Feb 11, 2019

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant