simcado.psf module

PSFs and PSFCubes

Todo

revise this opening text

Description

Car Sagan said

“If you want to bake an apple pie from scratch,

first you must create the universe”

Single PSFs

We need to start by generating a single PSF in order to generate a PSFCube. We need to know the spatial characteristics of the PSF: The commonalities of all PSFs are:

  • pix_width

  • pix_height

  • pix_res

  • type

The types of PSF offered: Moffat, Gaussian2D, Airy, Delta, Line, User For each of the PSF types we need to create a subclass of PSF. Each subclass takes its own list of parameters:

  • MoffatPSF (alpha, beta)

  • GaussianPSF (fwhm, eccentricity=0, angle=0)

  • AiryPSF (first_zero, eccentricity=0, angle=0)

  • DeltaPSF (x=0, y=0)

  • LinePSF (x0, x1, y0, y1, angle=0)

  • UserPSFCube (filename, ext_no=0)

Multiple PSFs in a Cube

To generate a PSF cube we need to know the spectral bins and the type of PSF. The bins are defined by a central wavelength, however a cube should also contain the edges of each bin so that transmission and emission can be re-binned properly. - lam_bin_centers - lam_bin_edges - lam_res

A PSF instance will have these additional arguments: - array … a 2D array to hold the PSF image

A psf instance will have these additional arguments: - cube … a (l,x,y) 3D array to hold the PSF cube

As far as input goes, psf should be able to accept a dictionary with the keywords necessary to build the cube.

Notes

All wavelength values are given in [um] All pixel dimensions are given in [arcsec] All angles are given in [deg]

Classes

PSF(object) psf(object)

Subclasses

MoffatPSF(PSF) GaussianPSF(PSF) AiryPSF(PSF) DeltaPSF(PSF) LinePSF(PSF) UserPSFCube(PSF)

Deltapsf(psf) Airypsf(psf) Gaussianpsf(psf) Moffatpsf(psf) CombinedPSFCube(psf) UserPSFCube(psf) ADC_psf(psf)

There are two types of psf object here: - a cube - a single psf image

The cube is essentially a list of psf images, homogenized in size Should we have separate classes for these?

Both PSF and psf can be created from a single model or through convolution of a list of PSF components

class simcado.psf.PSF(size, pix_res)[source]

Bases: object

Point spread function (single layer) base class

Parameters
sizeint

[pixel] the side length of the array

pix_resfloat

[arcsec] the pixel scale of the array

convolve(self, kernel)[source]

Convolve the PSF with another kernel. The PSF keeps its shape

Parameters
kernelnp.array, PSF

Either a numpy.ndarray or a PSF (sub)class

Returns
psf_newPSF
resample(self, new_pix_res)[source]

Resample the PSF array onto a new grid

Not perfect, but conserves flux

Parameters
new_pix_resfloat

[arcsec] the pixel resolution of the returned array

Returns
psf_newPSF

Examples

>>> new_PSF = old_PSF.resample(new_pix_res)
resize(self, new_size)[source]

Resize the PSF. The target shape is (new_size, new_size).

Parameters
new_sizeint

the new square dimensions of the PSF array in pixels

set_array(self, array, threshold=1e-15)[source]

Set the spatial flux distribution array for the PSF

Renormalise the array make sure there aren’t any negative values that will screw up the flux

Parameters
arraynp.ndarray

the array representing the PSF

thresholdfloat

by default set to 1E-15. Below this, the array is set to 0

class simcado.psf.PSFCube(lam_bin_centers)[source]

Bases: object

Class holding wavelength dependent point spread function.

Parameters
lam_bin_centersarray

[um] the centre of each wavelength slice

Notes

  • len(self) return the number of layers in the psf

  • self[i] returns the PSF object for layer i. If the __array__ function is called, self[i] will return the array associated with the instance e.g plt.imshow(self[i]) will plot PSF.array from self.psf_slices[i]

  • Maths operators *,+,- act equally on all PSF.arrays in self.psf_slices

convolve(self, kernel_list)[source]

Convolve a list of PSFs with a list of kernels

Parameters
kernel_listlist

list of PSF objects of 2D arrays

export_to_fits(self, filename, clobber=True)[source]

Export the psf to a FITS file for later use

Parameters
filenamestr
nearest(self, lam)[source]

Returns the PSF closest to the desired wavelength, lam [um]

Parameters
lamfloat

[um] desired wavelength

Returns
psf_slicePSF
resample(self, new_pix_res)[source]

Resample the the list of PSF array onto a new grid

Not perfect, but conserves flux

Parameters
new_pix_resfloat

[arcsec] the pixel resolution of the returned array

Returns
psf_newPSF

Examples

>>> new_PSF = old_PSF.resample(new_pix_res)
resize(self, new_size)[source]

Resize the list of PSFs. The target shape is (new_size, new_size).

Parameters
new_sizeint

[pixel] the new size of the PSF array in pixels

class simcado.psf.MoffatPSF(fwhm, **kwargs)[source]

Bases: simcado.psf.PSF

Generate a PSF for a Moffat function. Alpha is generated from the FWHM and Beta = 4.765 (from Trujillo et al. 2001)

Parameters
fwhmfloat

[arcsec] the equivalent FWHM of the Airy disk core.

sizeint

[pixel] the side length of the array

pix_resfloat

[arcsec] the pixel scale used in the array, default is 0.004

modestr

[‘oversample’,’linear_interp’] see Kernel2D (scipy.convolution.core)

class simcado.psf.MoffatPSFCube(lam_bin_centers, fwhm=None, **kwargs)[source]

Bases: simcado.psf.PSFCube

Generate a list of MoffatPSFs for wavelengths defined in lam_bin_centers

Parameters
lam_bin_centersarray, list

[um] a list with the centres of each wavelength slice

fwhmarray, list

[arcsec] the equivalent FWHM of the PSF.

diameterfloat

[m] diamter of primary mirror. Default is 39.3m.

modestr

[‘oversample’,’linear_interp’] see Kernel2D (scipy.convolution.core)

class simcado.psf.AiryPSF(fwhm, obscuration=0.0, size=255, pix_res=0.004, **kwargs)[source]

Bases: simcado.psf.PSF

Generate a PSF for an Airy function with an equivalent FWHM

Parameters
fwhmfloat

[arcsec] the equivalent FWHM of the Airy disk core.

sizeint

[pixel] the side length of the array

pix_resfloat

[arcsec] the pixel scale used in the array, default is 0.004

obscurationfloat

[0..1] radius of inner obscuration as fraction of aperture radius

modestr

[‘oversample’,’linear_interp’] see Kernel2D (scipy.convolution.core)

class simcado.psf.AiryPSFCube(lam_bin_centers, fwhm=None, **kwargs)[source]

Bases: simcado.psf.PSFCube

Generate a list of AiryPSFs for wavelengths defined in lam_bin_centers

Parameters
lam_bin_centersarray, list

[um] a list with the centres of each wavelength slice

fwhmarray, list

[arcsec] the equivalent FWHM of the PSF.

diameterfloat

[m] diamter of primary mirror. Default is 39.3m.

modestr

[‘oversample’,’linear_interp’] see Kernel2D (scipy.convolution.core)

class simcado.psf.GaussianPSF(fwhm, **kwargs)[source]

Bases: simcado.psf.PSF

Generate a PSF for an Gaussian function

Parameters
fwhmfloat

[arcsec] the equivalent FWHM of the Airy disk core.

sizeint

[pixel] the side length of the array

pix_resfloat

[arcsec] the pixel scale used in the array, default is 0.004

modestr

[‘oversample’,’linear_interp’] see Kernel2D (scipy.convolution.core)

class simcado.psf.GaussianPSFCube(lam_bin_centers, fwhm=None, **kwargs)[source]

Bases: simcado.psf.PSFCube

Generate a list of GaussianPSFs for wavelengths defined in lam_bin_centers

Parameters
lam_bin_centersarray, list

[um] a list with the centres of each wavelength slice

fwhmarray, list

[arcsec] the equivalent FWHM of the PSF.

diameterfloat

[m] diamter of primary mirror. Default is 39.3m.

modestr

[‘oversample’,’linear_interp’] see Kernel2D (scipy.convolution.core)

class simcado.psf.DeltaPSF(**kwargs)[source]

Bases: simcado.psf.PSF

Generate a PSF with a delta function at position (x,y)

Parameters
positiontuple

[pixel] where (x,y) on the array is where the delta function goes default is (x,y) = (0,0) and is the centre of the array

sizeint

[pixel] the side length of the array

pix_resfloat

[arcsec] the pixel scale used in the array, default is 0.004

class simcado.psf.DeltaPSFCube(lam_bin_centers, positions=(0, 0), **kwargs)[source]

Bases: simcado.psf.PSFCube

Generate a list of DeltaPSFs for wavelengths defined in lam_bin_centers

Parameters
lam_bin_centersarray

[um] the centre of each wavelength slice

positionstuple, list
(x,y) either a tuple, or a list of tuples denoting the

position of the delta function

pix_resfloat

[arcsec], pixel scale of the PSF. Default is 0.004 arcsec

sizeint

[pixel] side length of the PSF array

class simcado.psf.CombinedPSF(psf_list, **kwargs)[source]

Bases: simcado.psf.PSF

Generate a PSF from a collection of several PSFs.

Parameters
psf_listlist

A list of PSF objects

sizeint

[pixel] the side length in pixels of the array

class simcado.psf.CombinedPSFCube(psf_list, **kwargs)[source]

Bases: simcado.psf.PSFCube

Generate a list of CombinedPSFCubes from the list of psfs in psf_list

Parameters
lam_bin_centersarray, list

[um] a list with the centres of each wavelength slice

fwhmarray, list

[arcsec] the equivalent FWHM of the PSF.

diameterfloat

[m] diamter of primary mirror. Default is 39.3m.

class simcado.psf.UserPSF(filename, **kwargs)[source]

Bases: simcado.psf.PSF

Import a PSF from a FITS file.

Parameters
filenamestr

path to the FITS file to be read in

fits_extint, optional

the FITS extension number (default 0) for the data

pix_resfloat, optional

[arcsec] the pixel scale used in the array, default is 0.004

class simcado.psf.UserPSFCube(filename, lam_bin_centers)[source]

Bases: simcado.psf.PSFCube

Read in a psf previously saved as a FITS file

Keywords needed for a psf to be read in: NSLICES, WAVECENT, NAXIS1, CDELT1, PSF_TYPE, DESCRIPT

Parameters
filenamestr

the path to the FITS file holding the cube

Notes

A separate function will exist to convert foreign PSF FITS files into simcado.psf readable FITS files

simcado.psf.poppy_eelt_psf(plan='A', wavelength=2.2, mode='wide', size=1024, segments=None, filename=None, use_pupil_mask=True, **kwargs)[source]

Generate a PSF for the E-ELT for plan A or B with POPPY

Parameters
planstr, optional

[“A”, “B”], Default = “A” * Plan A is for a fully populated mirror (798 segments) * Plan B has the inner 5 rings missing (588 segments) and a further 5 random segments missing (583 segments)

wavelengthfloat, list, array, optional

[um] Default = 2.2um. The wavelength(s) for which a PSF should be made

modestr, optional

[“wide”, “zoom”] Default = “wide”. Sets the pixel size for each of the MICADO imaging modes - {“wide” : 4mas, “zoom” : 1.5mas}

sizeint, optional

[pixels] Default = 1024

segmentslist, optional

Default = None. A list of which segments to use for generating the E-ELT mirror. See get_eelt_segments()

filenamestr, optional

Default = None. If filename is not None, the resulting FITS object will be saved to disk

use_pupil_maskstr, optional

Default = True.

Returns
``astropy.HDUList``an astropy FITS object with the PSF in the data
extensions
Other Parameters
Values to pass to the POPPY functions
flattoflatfloat

[m] Default : 1.256

gapfloat

[m] Default : 0.004

secondary_radiusfloat

[m] Default : 5

n_supportsint

Default : 6

support_widthfloat

[m] Default : 0.2

support_angle_offsetfloat

[deg] Default : 0

n_missingint

Default : None. Number of segments missing

pupil_inner_radiusfloat

[m] Default : None # Plan A: 5.6m, Plan B: 11.5m

pupil_outer_radiusfloat

[m] Default : 19

simcado.psf.poppy_ao_psf(strehl, mode='wide', plan='A', size=1024, filename=None, **kwargs)[source]

Create a diffraction limited E-ELT PSF with a Seeing halo

Uses POPPY to create a diffraction limited PSF for the E-ELT for a certain configuration of mirror segments. The diffraction limited core is added to seeing halo, modelled by either a moffat or gassian profile.

Parameters
strehlfloat

[0 .. 1] The components are summed and weighted according to the strehl ratio psf = (1-strehl)*seeing_psf + (strehl)*diff_limited_psf

modestr, optional

[“wide”, “zoom”] Default = “wide”. Sets the pixel size for each of the MICADO imaging modes - {“wide” : 4mas, “zoom” : 1.5mas}

planstr, optional

[“A”, “B”], Default = “A” * Plan A is for a fully populated mirror (798 segments) * Plan B has the inner 5 rings missing (588 segments) and a further 5 random segments missing (583 segments)

sizeint, optional

[pixels] Default = 1024

filenamestr, optional

Default = None. If filename is not None, the resulting FITS object will be saved to disk

Returns
hdu_listastropy.HDUList

an astropy FITS object containing the PSFs for the given wavelengths

Other Parameters
fwhmfloat

[arcsec] Default : 0.8

psf_typestr

Default : “moffat”

wavelengthfloat

[um] Default : 2.2

segmentslist

Default : None. A list of which hexagonal poppy segments to use See get_eelt_segments()

flattoflatfloat

[m] Default : 1.256

gapfloat

[m] Default : 0.004

secondary_radiusfloat

[m] Default : 5

n_supportsint

Default : 6

support_widthfloat

[m] Default : 0.2

support_angle_offsetfloat

[deg] Default : 0

n_missingint

Default : None. Number of segments missing

pupil_inner_radiusfloat

[m] Default : None # Plan A: 5.6m, Plan B: 11.5m

pupil_outer_radiusfloat

[m] Default : 19

simcado.psf.seeing_psf(fwhm=0.8, psf_type='moffat', size=1024, pix_res=0.004, filename=None)[source]

Return a seeing limited PSF

Parameters
fwhmfloat, optional

[arcsec] Default = 0.8

psf_typestr, optional

[“moffat, “gaussian”] Default = “moffat”

sizeint, optional

[pixel] Default = 1024

pix_resfloat, optional

[arcsec] Default = 0.004

filenamestr, optional

Default = None. If filename is not None, the resulting FITS object will be saved to disk

Returns
seeing_psf2D-array

Notes

# Moffat description # https://www.gnu.org/software/gnuastro/manual/html_node/PSF.html # # Approximate parameters - Bendinelli 1988 # beta = 4.765 - Trujillo et al. 2001

simcado.psf.get_eelt_segments(plan='A', missing=None, return_missing_segs=False, inner_diam=10.6, outer_diam=39.0)[source]

Generate a list of segments for POPPY for the E-ELT

Parameters
planstr, optional

[“A”, “B”], Default = “A” * Plan A is for a fully populated mirror (798 segments) * Plan B has the inner 5 rings missing (588 segments) and a further 5 random segments missing (583 segments)

missingint, list, optional

Default = None. If an integer is passed, this many random segments are removed. If missing is a list, entries refer to specific segment IDs

return_missing_segsbool, optional

Defualt is False. Returns the missing segment numbers

inner_diamfloat, optional

[m] Default = 10.6. Diameter which produces ESO’s mirror configuration

outer_diamfloat, optional

[m] Default = 39.0. Diameter which produces ESO’s mirror configuration

Returns
segslist

A list of segment IDs for the mirror segments.

missinglist, conditional

Only returned if return_missing_segs == True. A list of segment IDS for the segments which are missing.

simcado.psf.make_foreign_PSF_cube(fnames, out_name=None, window=None, pix_res_orig=None, pix_res_final=None, wavelengths=None)[source]

Combine several PSF FITS images into a single PSF FITS file

Parameters
fnameslist

List of path names to the FITS files

out_namestr, optional

If out_name is not None, the resulting FITS file is saved under the name out_name

windowint, list, tuple, optional

If window is not None, a windowed section of the PSFs are extracted window = (left, right, top, bottom) window = square radius

Examples

>>> from glob import glob
>>> import simcado as sim
>>> fnames = glob("D:\Share_VW\Data_for_SimCADO\PSFs\yann_2016_11_10\*.fits")
>>> sim.psf.make_foreign_PSF_cube(fnames, "PSF_SCAO.fits",
                                  window=512,
                                  pix_res_orig=[0.0028, 0.0037, 0.00492],
                                  pix_res_final=[0.004, 0.004, 0.004],
                                  wavelengths=[1.25,1.65,2.2])
class simcado.psf.FieldVaryingPSF(**kwargs)[source]

Bases: simcado.fv_psf.DataContainer

apply_to(self, fov)[source]
get_kernel(self, fov)[source]
get_strehl_imagehdu(self, recalculate=False)[source]
property info
property strehl_imagehdu