• No se han encontrado resultados

MINIMIZACION Reducción en

Fuente: Autor

POPPY is designed to make it straightforward to implement your own custom optics classes, which will interoper- ate with all the built-in classes. Conceptually all that is needed is defining theget_transmissionand/orget_opd functions for each new class.

Many examples of this can be found inpoppy/optics.py

10.1 Defining a custom optic from an analytic function

The complex phasor of each optic is calculated automatically from that optic’s transmission (i.e. the throughput for the amplitude of the electromagnetic field) and optical path difference (i.e. the propagation delay in the phase of the electromagnetic field). Both of these quantities may vary as a function of position across the optic, and as a function of wavelength.

AnalyticOpticalElement subclasses must implement either or both of the functions get_transmission() and get_opd(). Each takes aWavefrontas its sole argument besidesself. All other necessary parameters should be set up as part of the__init__function defining your optic.

Note: This is new in version 0.5 of poppy; prior versions used a single function getPhasor to handle computing the entire complex phasor in one step including both the transmission and OPD components. Version 0.5 now pro- vides better flexibility and extensibility by allowing the transmission and OPD components to be defined in separate functions, and automatically takes care of combining them to produce the complex phasor behind the scenes.

Example skeleton code:

class myCustomOptic(poppy.AnalyticOpticalElement):

def __init__(self, *args, **kwargs):

""" If your optic has adjustible parameters, then save them as attributes here """

poppy.AnalyticOpticalElement.__init__(**kwargs)

def get_opd(self,wave):

(continues on next page)

poppy Documentation, Release 0.9.0

(continued from previous page)

y, x = self.get_coordinates(wave)

opd = some_function(x,y, wave.wavelength, self)

return opd

def get_transmission(self, wave):

y, x = self.get_coordinates(wave)

transmission = other_function(x,y, wave.wavelength, self)

return transmission

# behind the scenes poppy will calculate:

# phasor = transmission = np.exp(1.j * 2 * np.pi / wave.wavelength * opd)

Note the use of theself.get_coordinates()helper function, which returnsyandxarrays giving the coordinates as appopriate for the sampling of the suppliedwaveobject (by default in units of meters for most optics such as pupil planes, in arcseconds for image plane optics). You can use these coordinates to calculate the transmission and path delay appropriate for your optic. If your optic has wavelength dependent properties, access thewave.wavelength property to determine the the appropriate wavelength; this will be in units of meters.

Theget_coordinates()function automatically includes support for offset shifts and rotations for any analytic op- tic: just add ashift_x,shift_y or rotationattribute for your optic object, and the coordinates will be shifted accordingly. These parameters should be passed topoppy.AnalyticOpticalElement.__init__via the**kwargs mechanism.

10.2 Defining a custom optic from a FITS file

Of course, any arbitrary optic can be represented in discrete form in 2D arrays and then read into poppy using the FITSOpticalElement class. The physical parameters of the array are defined using fitsheaders.

The transmission array should contain floating point values between 0.0 and 1.0. These represent the local transmission of the electric field amplitude, not the total intensity.

The OPD array should contain floating point numbers (positive and negative) representing a path delay in some phys- ical units. The unit must be specified using theBUNITkeyword; allowed BUNITs are ‘meter’, ‘micron’, ‘nanometer’ and their standard metric abbreviations.

If you are using both an OPD and transmission together to define your optics, the arrays must have the same size. The spatial or angular scale of these arrays must also be indicated by a FITS header keyword. By default, poppy checks for the keywordPIXSCALEfor image plane pixel scale in arcseconds/pixel orPUPLSCALfor pupil plane scale in meters/pixel. However if your FITS file uses some alternate keyword, you can specify that keyword name with the pupilscale=argument in the call to theFITSOpticalElementconstructor, i.e.:

myoptic = poppy.FITSOpticalElement(transmission='transfile.fits', opd='opdfile.fits', pupilscale=

˓→"PIXELSCL")

Lastly if there is no such keyword available, you can specify the numerical scale directly via the same keyword by providing a float instead of a string:

myoptic = poppy.FITSOpticalElement(transmission='transfile.fits', opd='opdfile.fits', pupilscale=0.020)

poppy Documentation, Release 0.9.0

10.3 Creating a custom instrument

POPPY provides anInstrumentclass to simplify certain types of calculations. For example, the WebbPSF project usesInstrumentsubclasses to provide selectable filters, pupil masks, and image masks for the instruments on JWST. Any calculation you can set up with a bare POPPYOpticalSystemcan be wrapped with anInstrumentto present a friendlier API to end users. The Instrument will hold the selected instrument configuration and calculation options, passing them to a private method _getOpticalSystem()which implementors must override to build the OpticalSystemfor the PSF calculation.

The general notion of anInstrumentis that it consists of both

1. An optical system implemented in the usual fashion, optionally with several configurations such as selectable image plane or pupil plane stops or other adjustable properties, and

2. Some defined spectral bandpass(es) such as selectable filters. If thepysynphotmodule is available, it will be used to perform careful synthetic photometry of targets with a given spectrum observed in the given bandpass. Ifpysynphotis not installed, the code will fall back to a much simpler model assuming constant number of counts vs wavelength.

Configurable options such as optical masks and filters are specified as properties of the instrument instance; an appro- priateOpticalSystemwill be generated when thecalc_psf()method is called.

The Instrument is fairly complex, and has a lot of internal submethods used to modularize the calculation and allow subclassing and customization. For developing your own instrument classes, it may be useful to start with the instrument classes in WebbPSF as worked examples.

You will at a minimum want to override the following class methods: • _getOpticalSystem

• _getFilterList • _getDefaultNLambda • _getDefaultFOV • _getFITSHeader

For more complicated systems you may also want to override: • _validateConfig

• _getSynphotBandpass • _applyJitter

AnInstrumentwill get its configuration from three places: (1) The__init__method of theInstrumentsubclass

During __init__, the subclass can set important attributes likepixelscale, add a custom pupiloptic and OPD map, and set a default filter. (n.b. The current implementation may not do what you expect if you are accustomed to calling the superclass’ __init__at the end of your subclass’__init__method. Look at the implementation inpoppy/instrument.pyfor guidance.)

(2) Theoptionsdictionary attribute on theInstrumentsubclass

The options dictionary allows you to set a subset of options that are loosely considered to be independent of the instrument configuration (e.g. filter wheels) and of the particular calculation. This includes offsetting the source from the center of the FOV, shifting the pupil, applying jitter to the final image, or forcing the parity of the final output array.

poppy Documentation, Release 0.9.0

Users are free to introduce new options by documenting an option name and retrieving the value at an appropriate point in their implementation of_getOpticalSystem()(to which the options dictionary is passed as keyword argumentoptions).

(3) Thecalc_psf()method of theInstrumentsubclass

For interoperability, it’s not recommended to change the function signature ofcalc_psf(). However, it is an additional way that users will pass configuration information into the calculation, and a starting point for more involved customization that cannot be achieved by overriding one of the private methods above.

Be warned that thepoppy.InstrumentAPI evolved in tandem with WebbPSF, and certain things are subject to change as we extend it to use cases beyond the requirements of WebbPSF.

CHAPTER

11