def spaxel_scale(datacube, head, spaxel): '''Function that takes 3D datacube or 2D image and rebins it to chosen spaxel scale. Reads spaxel scale of input datacube from header keywords CDELT1/2. Inputs: datacube: 3D datacube or 2D image head: header file spaxel: spaxel scale mas (x, y) Outputs: new_cube: datacube (or 2D image) rebinned to chosen spaxel scale new_head: updated header file ''' print 'Spaxel scale' try: z, y, x = datacube.shape except: y, x = datacube.shape cdelt1 = head["CDELT1"] cdelt2 = head["CDELT2"] #total field of view in mas x_field = cdelt1 * x y_field = cdelt2 * y x_newsize = int(n.round(x_field / float(spaxel[0]), 0)) y_newsize = int(n.round(y_field / float(spaxel[1]), 0)) try: newcube = n.zeros((z, y_newsize, x_newsize), dtype=n.float64) for i in xrange(z): newcube[i, :, :] = frebin(datacube[i, :, :], (x_newsize, y_newsize), total=True) except: newcube = frebin(datacube, (x_newsize, y_newsize), total=True) head['CDELT1'] = (spaxel[0], "mas") head['CDELT2'] = (spaxel[1], "mas") head['NAXIS1'] = int(x_newsize) head['NAXIS2'] = int(y_newsize) print 'Spaxel scale - done!' return newcube, head
def spaxel_scale(datacube, head, spaxel): '''Function that takes 3D datacube or 2D image and rebins it to chosen spaxel scale. Reads spaxel scale of input datacube from header keywords CDELT1/2. Inputs: datacube: 3D datacube or 2D image head: header file spaxel: spaxel scale mas (x, y) Outputs: new_cube: datacube (or 2D image) rebinned to chosen spaxel scale new_head: updated header file ''' print 'Spaxel scale' try: z, y, x = datacube.shape except: y, x = datacube.shape cdelt1 = head["CDELT1"] cdelt2 = head["CDELT2"] #total field of view in mas x_field = cdelt1*x y_field = cdelt2*y x_newsize = n.round(x_field/float(spaxel[0]),0) y_newsize = n.round(y_field/float(spaxel[1]),0) try: newcube = n.zeros((z, y_newsize, x_newsize), dtype=n.float64) for i in xrange(z): newcube[i,:,:] = frebin(datacube[i,:,:], (x_newsize, y_newsize), total=True) except: newcube = frebin(datacube, (x_newsize, y_newsize), total=True) head['CDELT1'] = (spaxel[0], "mas") head['CDELT2'] = (spaxel[1], "mas") head['NAXIS1'] = int(x_newsize) head['NAXIS2'] = int(y_newsize) print 'Spaxel scale - done!' return newcube, head
def create_psf_channel(params, iteration, psfspax, output_spax, array_dim, aperture, res_jitter): '''Function that creates an AO PSF image given the parameter values and sampling scale. Inputs: psfparams: Dictionary containing parameter arrays iteration: Iteration value through wavelength array psfspax: PSF sampling scale [mas/spaxel] output_spax: Output sampling scale tuple (x, y) [mas/spaxel] array_dim: Size of PSF array aperture: List containing telescope diameter [m] and obsc. ratio res_jitter: value of residual telescope jitter [mas] Outputs: psf = 2D PSF array ''' #array = r_values([array_dim, array_dim], [(psfspax/1000.)*array_dim,(psfspax/1000.)*array_dim]) array = dist_arr(array_dim, psfspax / 1000.) # airy = obsc_airy(array, params['oh'][iteration], params['ow'][iteration]*rad_conv, aperture[1]) # moff1 = moffat(array, params['mh'][iteration], params['mw'][iteration]*rad_conv, params['mq'][iteration]) # lor = lorentz(array, params['lh'][iteration], params['lp'][iteration]*rad_conv, params['lw'][iteration]*rad_conv) # moff2 = moffat(array, params['m2h'][iteration], params['m2w'][iteration]*rad_conv, params['m2q'][iteration]) airy = obsc_airy(array, params['oh'][iteration], params['ow'] * rad_conv, aperture[1]) moff1 = moffat(array, params['mh'][iteration], params['mw'][iteration] * rad_conv, params['mq'][iteration]) lor = lorentz(array, params['lh'][iteration], params['lp'][iteration] * rad_conv, params['lw'][iteration] * rad_conv) moff2 = moffat(array, params['m2h'][iteration], params['m2w'][iteration] * rad_conv, params['m2q'][iteration]) channel = (airy + moff1 + lor + moff2) #Apply residual jitter channel /= channel.sum() #normalise psf = residual_jitter(channel, psfspax, res_jitter) #Frebin PSF up to same sampling as datacube channels psf /= psf.sum() #normalise #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) import numpy return psf
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
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
def create_psf_channel(params, iteration, psfspax, output_spax, array_dim, aperture, res_jitter): '''Function that creates an AO PSF image given the parameter values and sampling scale. Inputs: psfparams: Dictionary containing parameter arrays iteration: Iteration value through wavelength array psfspax: PSF sampling scale [mas/spaxel] output_spax: Output sampling scale tuple (x, y) [mas/spaxel] array_dim: Size of PSF array aperture: List containing telescope diameter [m] and obsc. ratio res_jitter: value of residual telescope jitter [mas] Outputs: psf = 2D PSF array ''' #array = r_values([array_dim, array_dim], [(psfspax/1000.)*array_dim,(psfspax/1000.)*array_dim]) array = dist_arr(array_dim, psfspax/1000.) airy = obsc_airy(array, params['oh'][iteration], params['ow'][iteration]*rad_conv, aperture[1]) moff1 = moffat(array, params['mh'][iteration], params['mw'][iteration]*rad_conv, params['mq'][iteration]) lor = lorentz(array, params['lh'][iteration], params['lp'][iteration]*rad_conv, params['lw'][iteration]*rad_conv) moff2 = moffat(array, params['m2h'][iteration], params['m2w'][iteration]*rad_conv, params['m2q'][iteration]) channel = (airy + moff1 + lor + moff2) #Apply residual jitter channel /= channel.sum() #normalise psf = residual_jitter(channel, psfspax, res_jitter) #Frebin PSF up to same sampling as datacube channels psf /= psf.sum() #normalise #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
def spaxel_scale(datacube, head, spaxel): """Function that takes datacube and rebins it to chosen spaxel scale. Reads spaxel scale of input datacube from header keywords CDELT1/2. Inputs: datacube: science datacube head: header file spaxel: spaxel scale mas (x, y) Outputs: new_cube: datacube rebinned to chosen spaxel scale new_head: updated header file """ print "Spaxel scale" z, y, x = datacube.shape cdelt1 = head["CDELT1"] cdelt2 = head["CDELT2"] # total field of view in mas x_field = cdelt1 * x y_field = cdelt2 * y x_newsize = n.round(x_field / float(spaxel[0]), 0) y_newsize = n.round(y_field / float(spaxel[1]), 0) newcube = n.zeros((z, y_newsize, x_newsize), dtype=n.float64) for i in xrange(z): newcube[i, :, :] = frebin(datacube[i, :, :], (x_newsize, y_newsize), total=True) head["CDELT1"] = (spaxel[0], "mas") head["CDELT2"] = (spaxel[1], "mas") head["NAXIS1"] = int(x_newsize) head["NAXIS2"] = int(y_newsize) print "Spaxel scale - done!" return newcube, head
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
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