Beispiel #1
0
def residual_jitter(array, array_spax, res_jitt):
    '''Function that takes wavelength channel array and convolves with
    Gaussian of FWHM given by res_jitt.

    Inputs:

        array: 2D array corresponding to wavelength channel
        array_spax: Spatial scale of array [mas/pix]
        res_jitt: Residual jitter sigma in units of [mas]
                  FWHM = 2.*n.sqrt(2.*n.log(2.))*sigma

    Outputs:

        jitt_array: New array of jittered PSF.
    '''

    #If res_jitt == 0, ignore function and return array.
    if res_jitt == 0.:
        return array
    else:
        fwhm_jitt = 2. * n.sqrt(2. * n.log(2.)) * res_jitt
        pix_fwhm = abs(fwhm_jitt) / (array_spax)
        g_array = Gauss2D(array.shape[0], pix_fwhm)

        #Convolve using FFTs
        conv_array = n.fft.ifft2(n.fft.fft2(array) * n.fft.fft2(g_array))
        jitt_array = n.fft.fftshift(conv_array.real)

        return jitt_array
Beispiel #2
0
def create_instpsf(array_dim, psfspax, output_spax, psfoutspax):
    '''Function that creates an instrument PSF array given the
    parameter values and sampling scale.

    Inputs:

        array_dim: Size of PSF array
        psfspax: PSF sampling scale [mas/spaxel]
        output_spax: Output sampling scale tuple (x, y) [mas/spaxel]
        psfoutspax: PSF convolution sampling scale to match datacube: tuple (x, y) [mas/spaxel]

    Outputs:

        instpsf = 2D PSF array

    '''

    #FWHM of Instrument PSF depending on output spaxel scale
    #Factors taken into account:
    #design image quality, manufacturing and assembly tolerances, vibration, flexure, diff refraction,
    #Also interpolating the data back onto a regular grid.
    #The interpolation adds another contribution of 0.8-1.8 PIXEL FWHM.
    #So a reasonable assumption: 1.1 pix FWHM.

    #FWHMs given in mas according to output spaxel scale
    instpsf_data = {
        (30., 60.): 65.,
        (20., 20.): 34.,
        (10., 10.): 17.,
        (4., 4.): 6.
    }
    #print 'SPAX = ', output_spax
    try:
        FWHM = instpsf_data[output_spax]
        #print 'FWHM = ', FWHM
        instpsf = Gauss2D(array_dim, FWHM / float(psfspax))
    except:
        #print 'Non-HARMONI spaxel scale - no instrument PSF'
        instpsf = n.zeros([array_dim, array_dim], dtype=float)
        instpsf[array_dim / 2, array_dim / 2] = 1.0

    #total field of view in mas
    x_field = array_dim * psfspax
    y_field = array_dim * psfspax
    x_newsize = x_field / float(psfoutspax[0])
    y_newsize = y_field / float(psfoutspax[1])

    instpsf = frebin(instpsf, (x_newsize, y_newsize), total=True)

    return instpsf
Beispiel #3
0
def create_Gausspsf_channel(wave, seeing, aperture, res_jitter, array_dim,
                            Nyquist, psfspax, output_spax):
    '''Function that creates a 2D spatial Gaussian PSF.
    The FWHM of the Gaussian is depends on wavelength in the following way:

    FWHM(radians) = 0.98 Lambda/r_0
    r_0 = A Lambda^(6/5.)
    FWHM(arcsec) = (0.98/A)/Lambda^(1/5.)

    Inputs:

        wave: wavelength [microns]
        seeing: FWHM value of the seeing at 500nm (V-band) in arcseconds.
        aperture: List containing [diameter of telescope, obscuration ratio].
                  Diameter only used when Nyquist=True.
        array_dim: Spatial size of PSF arrays.
        Nyquist: Boolean - True returns Nyquist sampling for each wavelength channel.
                         - False uses value of spaxel.
        psfspax: Initial spatial sampling value [mas].
        output_spax: Output spatial sampling [mas].


    Output:

        psf: PSF array for given wavelength.

    '''

    ##    lam = 500.E-9
    ##    #Compute r_0 from given seeing value
    ##    r_0 = 0.98*lam/float(seeing/206265.)
    ##
    ##    #Use r_0 to find A
    ##    A = r_0/lam**(6/5.)
    ##
    ##    #Use A to find constant for FWHM propto Lambda**(-1/5) equation
    ##    B = 0.98*206265./A

    r0 = 0.976 * 500.E-9 / float(seeing) * (180. / n.pi *
                                            3600.) * (wave / 0.5)**1.2  #in m
    fwhm = seeing * (wave / 0.5)**(-0.2) * n.sqrt(
        1. + (1. / (1. + 300. * aperture[0] / 23.) - 1) * 2.183 *
        (r0 / 23.)**(0.356))  #in arcsec

    if Nyquist:
        #fwhm = B/float((wave*(1.E-6))**(1/5.)) #in arcsec
        diff = wave * (1.E-6) / (2. * float(aperture[0]))
        diff *= 206265  #in arcsec/spaxel
        channel = Gauss2D(array_dim, fwhm / diff)
        #Apply residual jitter
        psf = residual_jitter(channel, diff, res_jitter)

    elif not Nyquist:
        spax = psfspax / 1000.  #in arcsec/spaxel
        #fwhm = B/float((wave*(1.E-6))**(1/5.)) #in arcsec
        channel = Gauss2D(array_dim, fwhm / spax)
        #Apply residual jitter
        psf = residual_jitter(channel, spax, res_jitter)

    #Normalise PSF
    psf /= psf.sum()

    #Frebin PSF up to same sampling as datacube channels

    #total field of view in mas
    x_field = array_dim * psfspax
    y_field = array_dim * psfspax
    x_newsize = x_field / float(output_spax[0])
    y_newsize = y_field / float(output_spax[1])

    psf = frebin(psf, (x_newsize, y_newsize), total=True)

    return psf