示例#1
0
def wavelength_loop(cube, head, wavels, out_cube, newsize, outspax):
    '''Function to take input datacube and process it iteratively through
    each wavelength channel as follows:
    - Generate PSF array for given channel
    - Add effect of ADR to channel
    - Convolve cube channel with PSF
    - Frebin up to chosen output spaxel scale

    Inputs:

        cube: Datacube
        head: Datacube header
        wavels: Wavelength array
        out_cube: Empty output cube
        newsize: tuple containing (x_newsize, y_newsize) array sizes
        outspax: output spaxels (x, y) (mas, mas)

    Output:

        cube: Processed cube
        head: Updated header

    '''

    nspec = wp.NIRSpec()
    nspec.pupilopd = None
    print 'OPD = ', nspec.pupilopd

    oversamp = 1000. / float(outspax[0])

    for l in xrange(len(wavels)):
        #Print percentage bar
        update_progress(n.round(l / float(len(wavels)), 2))

        #Create PSF channel
        psf = nspec.calcPSF(outfile=None,
                            source=None,
                            filter=None,
                            nlambda=None,
                            monochromatic=wavels[l] * 1.E-6,
                            oversample=oversamp,
                            fov_arcsec=5,
                            rebin=False)

        psf = psf[0].data

        #Convolve cube channel with PSF channel
        channel = psf_convolve(cube[l, :, :], psf)

        #Frebin datacube up to output spaxel scale
        newsize = (int(newsize[0]), int(newsize[1]))
        channel *= (head['CDELT1'] * head['CDELT2'] * 1.E-6)
        channel = frebin(channel, (newsize[0], newsize[1]), total=True)
        channel /= (outspax[0] * outspax[1] * 1.E-6)

        #Add channel to output cube
        out_cube[l, :, :] = channel

    return out_cube, head
def sky_background(wavels, delta_lambda, dit):
    '''Function that generates a sky background curve combining
    sky continuum, sky thermal emission and sky emission lines.
    
    Inputs:
        wavels: array of wavelengths for datacube
        delta_lambda: resolution element [um]
        dit: exposure time [s]. This determins how the sky emission
             line amplitudes vary through the exposure.
        
    Outputs:
        sky_bg_curve: array of total sky background
                  [units of photons/s/m^2/um/arcsec^2]
                  for each wavelength value in wavels
    '''

    #Load up all datafile using n.genfromtxt(...)
    #sky_em = n.genfromtxt(bgpath+'ASM_background/radiance_resolution_0.15_angstroms_MICRONS.txt')
    sky_em = n.genfromtxt(
        os.path.join(
            bgpath,
            'ASM_background/radiance_resolution_0.15_angstroms_MICRONS.txt'))

    #Cut down data to relevent region.
    se_start_arg = n.where(sky_em[:, 0] < wavels[0])[0][-1]
    se_end_arg = n.where(sky_em[:, 0] > wavels[-1])[0][0]
    sky_em_slice = sky_em[se_start_arg:se_end_arg + 1, :]

    if type(delta_lambda) == n.ndarray:
        #Low resolution mode. Use low_res_mode function to generate sky emission spectrum
        sky_em_spec = low_res_spec(sky_em, delta_lambda, False)
        binned_sky_em = sky_em_spec[:, 1].copy()

    else:
        #Convolve sky transmission array with Gaussian LSF of
        #FWHM = sqrt(new_resolution**2-old_resolution**2)
        #to fold in spectrum for each spectral pixel.
        input_disp = sky_em[1, 0] - sky_em[0, 0]
        sigma = n.sqrt(delta_lambda**2 -
                       input_disp**2) / (2. * n.sqrt(2. * n.log(2.)))

        conv_sky_em = gauss_convolve(sky_em_slice,
                                     sigma,
                                     lambda_space='Linear')
        ###new 30-05-14
        conv_sky_em_ph = conv_sky_em[:,
                                     1] * input_disp  #convert to units of photons/s/m^2/arcsec^2
        binned_sky_em_ph = frebin(
            conv_sky_em_ph.reshape(len(conv_sky_em_ph), 1), (1, len(wavels)),
            True)  #Total photons conserved
        binned_sky_em = binned_sky_em_ph / float(
            wavels[1] -
            wavels[0])  #reconvert back to photons/s/m^2/um/arcsec^2

    binned_sky_em.shape = (len(wavels), 1, 1)
    return binned_sky_em
示例#3
0
def pp_wavelength_channel(chann, head, wave, l, newsize, outspax):
    '''Function to take input datacube and process it iteratively through
    each wavelength channel as follows:
    - Generate PSF array for given channel
    - Add effect of ADR to channel
    - Convolve cube channel with PSF
    - Frebin up to chosen output spaxel scale

    Inputs:

        chann: cube channel
        head: Datacube header
        wave: wavelength [um]
        l: iteration no.
        out_cube: Empty output cube
        newsize: tuple containing (x_newsize, y_newsize) array sizes
        outspax: tuple containing (x, y) output spaxel scales

    Output:

        cube: Processed cube
        head: Updated header
        inspax: Input spaxel scale (mas, mas)
        outspax: Output spaxel scale (mas, mas)

    '''

    nspec = wp.NIRSpec()
    nspec.pupilopd = None
    #print 'OPD = ', nspec.pupilopd

    oversamp = 1000. / float(outspax[0])

    #Create PSF channel
    #print 'Wavelength = ', wave*1.E-6, 'm'
    psf = nspec.calcPSF(outfile=None,
                        source=None,
                        filter=None,
                        nlambda=None,
                        monochromatic=wave * 1.E-6,
                        oversample=oversamp,
                        fov_arcsec=5,
                        rebin=False)
    psf = psf[0].data

    #Convolve cube channel with PSF channel
    chann = psf_convolve(chann, psf)

    #Frebin datacube up to output spaxel scale
    newsize = (int(newsize[0]), int(newsize[1]))
    chann *= (head['CDELT1'] * head['CDELT2'] * 1.E-6)
    chann = frebin(chann, (newsize[0], newsize[1]), total=True)
    chann /= (outspax[0] * outspax[1] * 1.E-6)

    return chann, l
示例#4
0
def wavelength_loop(cube, head, wavels, out_cube, newsize, outspax):
    '''Function to take input datacube and process it iteratively through
    each wavelength channel as follows:
    - Generate PSF array for given channel
    - Add effect of ADR to channel
    - Convolve cube channel with PSF
    - Frebin up to chosen output spaxel scale

    Inputs:

        cube: Datacube
        head: Datacube header
        wavels: Wavelength array
        out_cube: Empty output cube
        newsize: tuple containing (x_newsize, y_newsize) array sizes
        outspax: output spaxels (x, y) (mas, mas)

    Output:

        cube: Processed cube
        head: Updated header

    '''

    nspec = wp.NIRSpec()
    nspec.pupilopd = None
    print 'OPD = ', nspec.pupilopd

    oversamp = 1000./float(outspax[0])

    for l in xrange(len(wavels)):
        #Print percentage bar
        update_progress(n.round(l/float(len(wavels)),2))

        #Create PSF channel
        psf = nspec.calcPSF(outfile=None, source=None, filter=None, nlambda=None,
                            monochromatic=wavels[l]*1.E-6, oversample=oversamp,
                            fov_arcsec=5, rebin=False)

        psf = psf[0].data

        #Convolve cube channel with PSF channel
        channel = psf_convolve(cube[l,:,:], psf)

        #Frebin datacube up to output spaxel scale
        newsize = (int(newsize[0]), int(newsize[1]))
        channel *= (head['CDELT1']*head['CDELT2']*1.E-6)
        channel = frebin(channel, (newsize[0],newsize[1]), total=True)
        channel /= (outspax[0]*outspax[1]*1.E-6)

        #Add channel to output cube
        out_cube[l,:,:] = channel

    return out_cube, head
示例#5
0
def pp_wavelength_channel(chann, head, wave, l, newsize, outspax):
    '''Function to take input datacube and process it iteratively through
    each wavelength channel as follows:
    - Generate PSF array for given channel
    - Add effect of ADR to channel
    - Convolve cube channel with PSF
    - Frebin up to chosen output spaxel scale

    Inputs:

        chann: cube channel
        head: Datacube header
        wave: wavelength [um]
        l: iteration no.
        out_cube: Empty output cube
        newsize: tuple containing (x_newsize, y_newsize) array sizes
        outspax: tuple containing (x, y) output spaxel scales

    Output:

        cube: Processed cube
        head: Updated header
        inspax: Input spaxel scale (mas, mas)
        outspax: Output spaxel scale (mas, mas)

    '''

    nspec = wp.NIRSpec()
    nspec.pupilopd = None
    #print 'OPD = ', nspec.pupilopd

    oversamp = 1000./float(outspax[0])

    #Create PSF channel
    #print 'Wavelength = ', wave*1.E-6, 'm'
    psf = nspec.calcPSF(outfile=None, source=None, filter=None, nlambda=None,
                        monochromatic=wave*1.E-6, oversample=oversamp,
                        fov_arcsec=5, rebin=False)
    psf = psf[0].data

    #Convolve cube channel with PSF channel
    chann = psf_convolve(chann, psf)

    #Frebin datacube up to output spaxel scale
    newsize = (int(newsize[0]), int(newsize[1]))
    chann *= (head['CDELT1']*head['CDELT2']*1.E-6)
    chann = frebin(chann, (newsize[0],newsize[1]), total=True)
    chann /= (outspax[0]*outspax[1]*1.E-6)

    return chann, l
示例#6
0
def my_convolution(chann, head, newsize, outspax, psf, instpsf):

    #Convolve cube channel with PSF channel
    chann = psf_convolve(chann, psf)

    #Convolve cube channel with instrument PSF
    chann = psf_convolve(chann, instpsf)

    #Frebin datacube up to output spaxel scale
    newsize = (int(newsize[0]), int(newsize[1]))
    #chann *= (head['CDELT1']*head['CDELT2']*1.E-6)
    chann = frebin(chann, (newsize[0],newsize[1]), total=True)
    #chann /= (outspax[0]*outspax[1]*1.E-6)

    return chann
def sky_background(wavels, delta_lambda, dit):
    '''Function that generates a sky background curve combining
    sky continuum, sky thermal emission and sky emission lines.
    
    Inputs:
        wavels: array of wavelengths for datacube
        delta_lambda: resolution element [um]
        dit: exposure time [s]. This determins how the sky emission
             line amplitudes vary through the exposure.
        
    Outputs:
        sky_bg_curve: array of total sky background
                  [units of photons/s/m^2/um/arcsec^2]
                  for each wavelength value in wavels
    '''
    
    #Load up all datafile using n.genfromtxt(...)
    #sky_em = n.genfromtxt(bgpath+'ASM_background/radiance_resolution_0.15_angstroms_MICRONS.txt')
    sky_em = n.genfromtxt(os.path.join(bgpath,'ASM_background/radiance_resolution_0.15_angstroms_MICRONS.txt'))
    
    #Cut down data to relevent region.
    se_start_arg = n.where(sky_em[:,0] < wavels[0])[0][-1]
    se_end_arg = n.where(sky_em[:,0] > wavels[-1])[0][0]
    sky_em_slice = sky_em[se_start_arg:se_end_arg+1,:]

    if type(delta_lambda) == n.ndarray:
        #Low resolution mode. Use low_res_mode function to generate sky emission spectrum
        sky_em_spec = low_res_spec(sky_em, delta_lambda, False)
        binned_sky_em = sky_em_spec[:,1].copy()

    else:
        #Convolve sky transmission array with Gaussian LSF of
        #FWHM = sqrt(new_resolution**2-old_resolution**2)
        #to fold in spectrum for each spectral pixel.
        input_disp = sky_em[1,0] - sky_em[0,0]
        sigma = n.sqrt(delta_lambda**2-input_disp**2)/(2.*n.sqrt(2.*n.log(2.)))
        
        conv_sky_em = gauss_convolve(sky_em_slice, sigma, lambda_space='Linear')
        ###new 30-05-14
        conv_sky_em_ph = conv_sky_em[:,1]*input_disp #convert to units of photons/s/m^2/arcsec^2
        binned_sky_em_ph = frebin(conv_sky_em_ph.reshape(len(conv_sky_em_ph),1), (1,len(wavels)), True) #Total photons conserved
        binned_sky_em = binned_sky_em_ph/float(wavels[1]-wavels[0]) #reconvert back to photons/s/m^2/um/arcsec^2
    
    binned_sky_em.shape = (len(wavels),1,1)
    return binned_sky_em
示例#8
0
def wavelength_loop(cube,
                    head,
                    wavels,
                    out_cube,
                    AO,
                    psfvars,
                    adrvals,
                    newsize,
                    outspax,
                    adr_switch='ON'):
    '''Function to take input datacube and process it iteratively through
    each wavelength channel as follows:
    - Generate PSF array for given channel
    - Add effect of ADR to channel
    - Convolve cube channel with PSF
    - Frebin up to chosen output spaxel scale

    Inputs:

        cube: Datacube
        head: Datacube header
        wavels: Wavelength array
        out_cube: Empty output cube
        AO: AO mode [LTAO, SCAO, Gaussian]
        psdvars: list containing [psfparams, psfspax, psfsize, [D,eps],
                                  res_jitter, seeing, user_psf, user_psflams]
        adrvals: array of ADR values
        newsize: tuple containing (x_newsize, y_newsize) array sizes
        outspax: tuple containing (x, y) output spaxel scales
        adr_switch: ON or OFF. Turns ADR effect on or off.

    Output:

        cube: Processed cube
        head: Updated header
        inspax: Input spaxel scale (mas, mas)
        outspax: Output spaxel scale (mas, mas)

    '''
    for l in xrange(len(wavels)):
        #Print percentage bar
        update_progress(n.round(l / float(len(wavels)), 2))

        #Create PSF channel
        #If user PSF and 2D image
        upsf = psfvars[-2]
        upsflams = psfvars[-1]
        if type(upsf) != str and type(upsflams) == str:
            psf = upsf
        #If User PSF and 3D cube
        elif type(upsf) != str and type(upsflams) != str:
            #Interpolate PSF cube
            interp = interp1d(upsflams, upsf, axis=0)
            psf = interp(wavels[l])

        elif AO == 'LTAO' or AO == 'SCAO' or AO == 'GLAO':
            psf = create_psf_channel(psfvars[0], l, psfvars[1],
                                     (head['CDELT1'], head['CDELT2']),
                                     psfvars[2], psfvars[3], psfvars[4])

        elif AO == 'Gaussian':
            psf = create_Gausspsf_channel(wavels[l],
                                          psfvars[5],
                                          psfvars[3],
                                          psfvars[4],
                                          psfvars[2],
                                          Nyquist=False,
                                          psfspax=psfvars[1],
                                          output_spax=(head['CDELT1'],
                                                       head['CDELT2']))

        else:
            print 'AO = ', AO
            raise ValueError('AO choice error!')

        #Create instrument PSF array
        instpsf = create_instpsf(psfvars[2], psfvars[1], outspax,
                                 (head['CDELT1'], head['CDELT2']))

        #Add ADR effect to channel
        if adr_switch == 'ON':
            cube[l, :, :] = add_ADR(cube[l, :, :], head, adrvals[l], 'spline3')

        #Convolve cube channel with PSF channel
        channel = psf_convolve(cube[l, :, :], psf)

        #Convolve cube channel with instrument PSF
        channel = psf_convolve(channel, instpsf)

        #Frebin datacube up to output spaxel scale
        newsize = (int(newsize[0]), int(newsize[1]))
        channel *= (head['CDELT1'] * head['CDELT2'] * 1.E-6)
        channel = frebin(channel, (newsize[0], newsize[1]), total=True)
        channel /= (outspax[0] * outspax[1] * 1.E-6)

        #Correct ADR effect
        if adr_switch == 'ON':
            adrhead = head.copy()
            adrhead['CDELT1'] = outspax[0]
            adrhead['CDELT2'] = outspax[1]
            channel = add_ADR(channel, adrhead, -1. * adrvals[l], 'spline3')

        #Add channel to output cube
        out_cube[l, :, :] = channel

    return out_cube, head
示例#9
0
def pp_wavelength_channel(chann, head, wave, l, AO, psfvars, adrval, newsize,
                          outspax, adr_switch):
    '''Function to take input datacube and process it iteratively through
    each wavelength channel as follows:
    - Generate PSF array for given channel
    - Add effect of ADR to channel
    - Convolve cube channel with PSF
    - Frebin up to chosen output spaxel scale

    Inputs:

        chann: cube channel
        head: Datacube header
        wave: wavelength [um]
        l: iteration no.
        out_cube: Empty output cube
        AO: AO mode [LTAO, SCAO, Gaussian]
        psfvars: list containing [psfparams, psfspax, psfsize,
                                  [D,eps], res_jitter, seeing, user_psf,
                                  user_psflams]
        adrval: ADR value
        newsize: tuple containing (x_newsize, y_newsize) array sizes
        outspax: tuple containing (x, y) output spaxel scales
        adr_switch: On or OFF. Turns ADR effect on or off

    Output:

        cube: Processed cube
        head: Updated header
        inspax: Input spaxel scale (mas, mas)
        outspax: Output spaxel scale (mas, mas)

    '''

    #Create PSF channel
    #If user PSF and 2D image
    upsf = psfvars[-2]
    upsflams = psfvars[-1]
    if type(upsf) != str and type(upsflams) == str:
        psf = upsf
    #If User PSF and 3D cube
    elif type(upsf) != str and type(upsflams) != str:
        #Interpolate PSF cube
        interp = interp1d(upsflams, upsf, axis=0)
        psf = interp(wave)

    elif AO == 'LTAO' or AO == 'SCAO' or AO == 'GLAO':
        psf = create_psf_channel(psfvars[0], l, psfvars[1],
                                 (head['CDELT1'], head['CDELT2']), psfvars[2],
                                 psfvars[3], psfvars[4])

    elif AO == 'Gaussian':
        psf = create_Gausspsf_channel(wave, psfvars[5], psfvars[3], psfvars[4],
                                      psfvars[2], False, psfvars[1],
                                      (head['CDELT1'], head['CDELT2']))

    else:
        print 'AO = ', AO
        raise ValueError('AO choice or user_PSF error!')

    #Create instrument PSF array
    instpsf = create_instpsf(psfvars[2], psfvars[1], outspax,
                             (head['CDELT1'], head['CDELT2']))

    #Add ADR effect to channel
    if adr_switch == 'ON':
        chann = add_ADR(chann, head, adrval, 'spline3')

    #Convolve cube channel with PSF channel
    chann = psf_convolve(chann, psf)

    #Convolve cube channel with instrument PSF
    chann = psf_convolve(chann, instpsf)

    #Frebin datacube up to output spaxel scale
    newsize = (int(newsize[0]), int(newsize[1]))
    chann *= (head['CDELT1'] * head['CDELT2'] * 1.E-6)
    chann = frebin(chann, (newsize[0], newsize[1]), total=True)
    chann /= (outspax[0] * outspax[1] * 1.E-6)

    #"Correct" ADR effect
    if adr_switch == 'ON':
        adrhead = head.copy()
        adrhead['CDELT1'] = outspax[0]
        adrhead['CDELT2'] = outspax[1]
        chann = add_ADR(chann, adrhead, -1. * adrval, 'spline3')

    return chann, l
def spectral_res(datacube, head, grating, wavels, gratings, spec_nyquist=True, spec_samp=1.):
    '''Function that takes input datacube and rebins it to the
    chosen spectral resolution. It convolves datacube along wavelength
    axis, interpolates all spaxels along wavelength axis then extracts
    pixel vales for each datacube wavelength channel. Function combines both
    spectral resolution choice and datacube chopping in wavelength axis.
    Option of bypassing spectral processing by setting band=='None' and
    spec_nyquist=True - this ignores wavelength dimension.

    Inputs:
        datacube: object datacube
        head: header file for object datacube
        grating: string representing chosen grating. Grating choice sets R and wavelength range
        wavels: wavelength array for datacube
        gratings: dictionary of grating parameters (lambda_min, lambda_max, R)
        spec_nyquist: Boolean - if True, 2 pixels per resolution element.
                              - if False, uses spec_samp value

    Outputs:
        scaled_cube: rebinned datacube
        head: updated header file
        new_wavels: new wavelength array for datacube
        delta_lambda: New resolution [um]
        lamb_per_pix: pixel dispersion [um/pixel]
        bandws[2]: output R
    '''

    print 'Spectral resolution and wavelength range.'
    print 'Chosen grating: ', grating

    bandws = gratings[grating]

    z, y, x = datacube.shape

    if bandws == None and spec_nyquist==False:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3']
    elif bandws != None and spec_nyquist==True:
        new_res = (bandws[0]+bandws[1])/(2.*bandws[2])
        lamb_per_pix = new_res/2.
    elif bandws != None and spec_nyquist==False:
        new_res = (bandws[0]+bandws[1])/(2.*bandws[2])
        lamb_per_pix = spec_samp/10000.
    elif bandws == None and spec_nyquist==True:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3'], 0
    else:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3'], 0

    print 'Current resolution = %.5f microns' % head['SPECRES']
    print 'Current sampling = %.5f microns' % head['CDELT3']
    print 'New resolution = %.5f microns' % new_res
    print 'New sampling = %.5f microns' % lamb_per_pix

    if head['SPECRES'] >= new_res:
        print 'WARNING: Input spectral resolution is coarser (or equal) than chosen output!'
        #Chose whether to convolve with LSF or simply resample.
        condition = raw_input('Do you want to convolve with Gaussian LSF of FWHM'
                                  ' given by band and chosen resolving power [y], or not [any other key]?: ')

        if condition=='y':
            print 'Convolving with LSF'
            #Generate Gaussian LSF of FWHM = (bandws[0]+bandws[1])/(2.*R)
            sig = new_res/(2.*n.sqrt(2.*n.log(2.)))
            gauss_array = Gauss(sig, head['CDELT3'])
            #Convolve datacube array with Gaussian along wavelength axis
            datacube = convolve1d(datacube, gauss_array[:,1], axis=0)

    else:
        print 'Input spectral resolution smaller than chosen output.'
        print 'Convolving with corresponding LSF.'
        #Generate Gaussian LSF of FWHM = sqrt(new_resolution**2-head['SPECRES']**2)
        sig = n.sqrt(new_res**2-head['SPECRES']**2)/(2.*n.sqrt(2.*n.log(2.)))
        gauss_array = Gauss(sig, head['CDELT3'])

        #Convolve datacube array with Gaussian along wavelength axis
        datacube = convolve1d(datacube, gauss_array[:,1], axis=0)


##    #New wavelength values from chosen photometric band (or ignore)
##    if bandws:
##        new_wavels = n.arange(bandws[0], bandws[1], lamb_per_pix)
##        new_wavels[-1] = bandws[1]
##        #Slice datacube down to size of new wavelength array
##        start = n.where(wavels < new_wavels[0])[0][-1]
##        end = n.where(wavels > new_wavels[-1])[0][0]
##        datacube = datacube[start:end+1,:,:]
##    elif not bandws:
##        new_wavels = n.arange(wavels[0], wavels[-1], lamb_per_pix)
##        new_wavels[-1] = wavels[-1]

    #####
    #Interpolate datacube onto regular pixel grid (irregular wavelength grid) with 10x hypersampling
    if wavels[0] <= bandws[0] and wavels[-1] >= bandws[1]:#cube wavelength range larger than grating choice
        print 'Cube wavelength range larger than grating: chopping down to grating range'

        new_wavels = n.arange(bandws[0], bandws[1]+lamb_per_pix/2., lamb_per_pix)
        new_wavels[-1] = bandws[1]
        start = n.where(wavels <= new_wavels[0])[0][-1]
        end = n.where(wavels >= new_wavels[-1])[0][0]
        #datacube = datacube[start:end+1,:,:]

    elif wavels[0] > bandws[0] and wavels[-1] < bandws[1]:#cube wavelength range inside grating choice
        print 'Cube wavelength range inside grating range'

        new_wavels = n.arange(wavels[0], wavels[-1]+lamb_per_pix/2., lamb_per_pix)
        new_wavels[-1] = wavels[-1]
        start = n.where(bandws[0] < wavels)[0][0]
        end = n.where(bandws[1] > wavels)[0][-1]
        #datacube = datacube[start:end+1,:,:]

    elif wavels[0] > bandws[0]:#cube short wavelength longer than grating shortest wavelength
        print 'Cube shortest wavelength larger than grating'

        new_wavels = n.arange(wavels[0], bandws[1]+lamb_per_pix/2., lamb_per_pix)
        new_wavels[-1] = bandws[1]
        start = n.where(bandws[0] < wavels)[0][0]
        end = n.where(bandws[1] > wavels)[0][-1]
        #datacube = datacube[start:end+1,:,:]

    elif wavels[-1] < bandws[1]:#cube longest wavelength shorter than grating longest wavelength
        print 'Cube longest wavelength shorter than grating'

        new_wavels = n.arange(bandws[0], wavels[-1]+lamb_per_pix/2., lamb_per_pix)
        new_wavels[-1] = wavels[-1]
        start = n.where(bandws[0] < wavels)[0][0]
        end = n.where(bandws[1] > wavels)[0][-1]
        #datacube = datacube[start:end+1,:,:]

    else:
        raise ValueError('Specres wavelength error!!!')

    #####

    new_cube = n.zeros((len(new_wavels), y, x), dtype=float)

    ###New 30-05-14
    #Put datacube flux into photon units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head['FUNITS'] == 'J/s/m2/A/arcsec2':
        datacube *= (head['CDELT3']*10000.)
    else:
        datacube *= head['CDELT3']

    #print 'Datacube sum = ', datacube.sum()

    #Bin up in spectral dimension to new pixel sampling
    #Iterate over x-axis and use frebin function on 2D y-z arrays
    for i in xrange(x):
            new_cube[:,:,i] = frebin(datacube[start:end+1,:,i], (y,len(new_wavels)), True)

    #print 'New cube sum = ', new_cube.sum()

    #Put datacube flux back into photons/wavelength units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head['FUNITS'] == 'J/s/m2/A/arcsec2':
        new_cube /= (lamb_per_pix*10000.)
    else:
        new_cube /= lamb_per_pix


    #Update header
    head['CRVAL3'] = new_wavels[0]
    head['CDELT3'] = (new_wavels[1]-new_wavels[0])
    head['NAXIS3'] = len(new_wavels)
    head['SPECRES'] = new_res

    print 'Spectral resolution and wavelength range - done!'

    #Return new_datacube, new_wavels, updated_header
    return new_cube, head, new_wavels, new_res, lamb_per_pix, bandws[2]
def spectral_res(datacube, head, R, band, wavels, spec_nyquist=True, spec_samp=1.):
    '''Function that takes input datacube and rebins it to the
    chosen spectral resolution. It convolves datacube along wavelength
    axis, interpolates all spaxels along wavelength axis then extracts
    pixel vales for each datacube wavelength channel. Function combines both
    spectral resolution choice and datacube chopping in wavelength axis.
    Option of bypassing spectral processing by setting band=='None' and
    spec_nyquist=True - this ignores wavelength dimension.

    Inputs:
        datacube: object datacube
        head: header file for object datacube
        R: spectral resolving power
        band: string representing wavelength band choice.
              Option of "None" which ignores photometric bands. 
        wavels: wavelength array for datacube
        spec_nyquist: Boolean - if True, 2 pixels per resolution element.
                              - if False, uses spec_samp value

    Outputs:
        scaled_cube: rebinned datacube
        head: updated header file
        new_wavels: new wavelength array for datacube
        delta_lambda: New resolution [um]
        lamb_per_pix: pixel dispersion [um/pixel]
    '''

    print 'Spectral resolution and wavelength range.'
    print 'Chosen resolution: ', R
    print 'Chosen band: ', band

    bands = {'V':(.47,.63),'R':(.63,.79), 'Iz':(.82,1.03),
             'J':(1.08,1.36), 'H':(1.46,1.83), 'K':(1.95,2.45),
             'V+R':(.47,.81), 'Iz+J':(.8,1.36), 'H+K':(1.45,2.45),
             'V-high':(.53,.59), 'R-high':(.61,.68),
             'z':(.82,.91), 'J-high':(1.17,1.29),
             'H-high':(1.545,1.715), 'K-high':(2.09,2.32),
             'None':None}

    bandws = bands[band]

    z, y, x = datacube.shape

    if bandws == None and spec_nyquist==False:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3']
    elif bandws != None and spec_nyquist==True:
        new_res = (bandws[0]+bandws[1])/(2.*R)
        lamb_per_pix = new_res/2.
    elif bandws != None and spec_nyquist==False:
        new_res = (bandws[0]+bandws[1])/(2.*R)
        lamb_per_pix = spec_samp/10000.
    elif bandws == None and spec_nyquist==True:
        #no convolution, just interpolate and read out new wavelengths
        #when sig=0, gauss returns [1.,1.] so convolution does nothing.
#        new_res = head['SPECRES']
        new_res = (wavels[0]+wavels[-1])/(2.*R)
        lamb_per_pix = new_res/2.
    else:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3']        

    print 'Current resolution = %.5f microns' % head['SPECRES']
    print 'Current sampling = %.5f microns' % head['CDELT3']
    print 'New resolution = %.5f microns' % new_res
    print 'New sampling = %.5f microns' % lamb_per_pix

    if head['SPECRES'] >= new_res:
        print 'WARNING: Input spectral resolution is coarser (or equal) than chosen output!'
        #Chose whether to convolve with LSF or simply resample.
        condition = raw_input('Do you want to convolve with Gaussian LSF of FWHM'
                                  ' given by band and chosen resolving power [y], or not [any other key]?: ')
                
        if condition=='y':
            print 'Convolving with LSF'
            #Generate Gaussian LSF of FWHM = (bandws[0]+bandws[1])/(2.*R)
            sig = new_res/(2.*n.sqrt(2.*n.log(2.)))
            gauss_array = Gauss(sig, head['CDELT3'])              
            #Convolve datacube array with Gaussian along wavelength axis
            datacube = convolve1d(datacube, gauss_array[:,1], axis=0)

    else:
        print 'Input spectral resolution smaller than chosen output.'
        print 'Convolving with corresponding LSF.'
        #Generate Gaussian LSF of FWHM = sqrt(new_resolution**2-head['SPECRES']**2)
        sig = n.sqrt(new_res**2-head['SPECRES']**2)/(2.*n.sqrt(2.*n.log(2.)))
        gauss_array = Gauss(sig, head['CDELT3'])
        
        #Convolve datacube array with Gaussian along wavelength axis
        datacube = convolve1d(datacube, gauss_array[:,1], axis=0)

    
    #New wavelength values from chosen photometric band (or ignore)
    if bandws:
        new_wavels = n.arange(bandws[0], bandws[1], lamb_per_pix)
        new_wavels[-1] = bandws[1]
        #Slice datacube down to size of new wavelength array
        start = n.where(wavels < new_wavels[0])[0][-1]
        end = n.where(wavels > new_wavels[-1])[0][0]
        datacube = datacube[start:end+1,:,:]
    elif not bandws:
        new_wavels = n.arange(wavels[0], wavels[-1], lamb_per_pix)
        new_wavels[-1] = wavels[-1]   
        
    new_cube = n.zeros((len(new_wavels), y, x), dtype=float)

    ###New 30-05-14
    #Put datacube flux into photon units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head['FUNITS'] == 'J/s/m2/A/arcsec2':
        datacube *= (head['CDELT3']*10000.)
    else:
        datacube *= head['CDELT3']

    #print 'Datacube sum = ', datacube.sum()

    #Bin up in spectral dimension to new pixel sampling
    #Iterate over x-axis and use frebin function on 2D y-z arrays
    for i in xrange(x):
            new_cube[:,:,i] = frebin(datacube[:,:,i], (y,len(new_wavels)),True)

    #print 'New cube sum = ', new_cube.sum()

    #Put datacube flux back into photons/wavelength units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head['FUNITS'] == 'J/s/m2/A/arcsec2':
        new_cube /= (lamb_per_pix*10000.)
    else:
        new_cube /= lamb_per_pix
        

    #Update header
    head.update('CRVAL3', new_wavels[0])
    head.update('CDELT3', (new_wavels[1]-new_wavels[0]))
    head.update('NAXIS3', len(new_wavels))
    head.update('SPECRES', new_res)

    print 'Spectral resolution and wavelength range - done!'
    
    #Return new_datacube, new_wavels, updated_header
    return new_cube, head, new_wavels, new_res, lamb_per_pix
示例#12
0
def spectral_res(datacube,
                 head,
                 grating,
                 wavels,
                 gratings,
                 spec_nyquist=True,
                 spec_samp=1.,
                 ignoreLSF=False):
    '''Function that takes input datacube and rebins it to the
    chosen spectral resolution. It convolves datacube along wavelength
    axis, interpolates all spaxels along wavelength axis then extracts
    pixel vales for each datacube wavelength channel. Function combines both
    spectral resolution choice and datacube chopping in wavelength axis.
    Option of bypassing spectral processing by setting band=='None' and
    spec_nyquist=True - this ignores wavelength dimension.

    Inputs:
        datacube: object datacube
        head: header file for object datacube
        grating: string representing chosen grating. Grating choice sets R and wavelength range
        wavels: wavelength array for datacube
        gratings: dictionary of grating parameters (lambda_min, lambda_max, R)
        spec_nyquist: Boolean - if True, 2 pixels per resolution element.
                              - if False, uses spec_samp value
        ignoreLSF: Boolean - ignore LSF convolution in spectral dimension

    Outputs:
        scaled_cube: rebinned datacube
        head: updated header file
        new_wavels: new wavelength array for datacube
        delta_lambda: New resolution [um]
        lamb_per_pix: pixel dispersion [um/pixel]
        resol: output R
    '''

    print 'Spectral resolution and wavelength range.'
    print 'Chosen grating: ', grating

    bandws = gratings[grating]

    z, y, x = datacube.shape

    if ignoreLSF == True:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3'], 0
    if bandws == None and spec_nyquist == False:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3'], 0
    elif bandws != None and spec_nyquist == True:
        #new_res = (bandws[0]+bandws[1])/(2.*bandws[2])
        new_res = bandws[2]
        lamb_per_pix = new_res / 2.
    elif bandws != None and spec_nyquist == False:
        #new_res = (bandws[0]+bandws[1])/(2.*bandws[2])
        new_res = bandws[2]
        lamb_per_pix = spec_samp / 10000.
    elif bandws == None and spec_nyquist == True:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3'], 0
    else:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3'], 0

    print 'Current resolution = %.5f microns' % head['SPECRES']
    print 'Current sampling = %.5f microns' % head['CDELT3']
    print 'New resolution = %.5f microns' % new_res
    print 'New sampling = %.5f microns' % lamb_per_pix

    if head['SPECRES'] >= new_res:
        print 'WARNING: Input spectral resolution is coarser (or equal) than chosen output!'
        #Chose whether to convolve with LSF or simply resample.
        condition = raw_input(
            'Do you want to convolve with Gaussian LSF of FWHM'
            ' given by band and chosen resolving power [y], or not [any other key]?: '
        )

        if condition == 'y':
            print 'Convolving with LSF'
            #Generate Gaussian LSF of FWHM = (bandws[0]+bandws[1])/(2.*R)
            sig = new_res / (2. * n.sqrt(2. * n.log(2.)))
            gauss_array = Gauss(sig, head['CDELT3'])
            #Convolve datacube array with Gaussian along wavelength axis
            datacube = convolve1d(datacube, gauss_array[:, 1], axis=0)

    else:
        print 'Input spectral resolution smaller than chosen output.'
        print 'Convolving with corresponding LSF.'
        #Generate Gaussian LSF of FWHM = sqrt(new_resolution**2-head['SPECRES']**2)
        sig = n.sqrt(new_res**2 -
                     head['SPECRES']**2) / (2. * n.sqrt(2. * n.log(2.)))
        gauss_array = Gauss(sig, head['CDELT3'])

        #Convolve datacube array with Gaussian along wavelength axis
        datacube = convolve1d(datacube, gauss_array[:, 1], axis=0)

##    #New wavelength values from chosen photometric band (or ignore)
##    if bandws:
##        new_wavels = n.arange(bandws[0], bandws[1], lamb_per_pix)
##        new_wavels[-1] = bandws[1]
##        #Slice datacube down to size of new wavelength array
##        start = n.where(wavels < new_wavels[0])[0][-1]
##        end = n.where(wavels > new_wavels[-1])[0][0]
##        datacube = datacube[start:end+1,:,:]
##    elif not bandws:
##        new_wavels = n.arange(wavels[0], wavels[-1], lamb_per_pix)
##        new_wavels[-1] = wavels[-1]

#####
#Interpolate datacube onto regular pixel grid (irregular wavelength grid) with 10x hypersampling
    if wavels[0] <= bandws[0] and wavels[-1] >= bandws[
            1]:  #cube wavelength range larger than grating choice
        print 'Cube wavelength range larger than grating: chopping down to grating range'

        new_wavels = n.arange(bandws[0], bandws[1] + lamb_per_pix / 2.,
                              lamb_per_pix)
        new_wavels[-1] = bandws[1]
        start = n.where(wavels <= new_wavels[0])[0][-1]
        end = n.where(wavels >= new_wavels[-1])[0][0]
        #datacube = datacube[start:end+1,:,:]

    elif wavels[0] > bandws[0] and wavels[-1] < bandws[
            1]:  #cube wavelength range inside grating choice
        print 'Cube wavelength range inside grating range'

        new_wavels = n.arange(wavels[0], wavels[-1] + lamb_per_pix / 2.,
                              lamb_per_pix)
        new_wavels[-1] = wavels[-1]
        start = n.where(bandws[0] < wavels)[0][0]
        end = n.where(bandws[1] > wavels)[0][-1]
        #datacube = datacube[start:end+1,:,:]

    elif wavels[0] > bandws[
            0]:  #cube short wavelength longer than grating shortest wavelength
        print 'Cube shortest wavelength larger than grating'

        new_wavels = n.arange(wavels[0], bandws[1] + lamb_per_pix / 2.,
                              lamb_per_pix)
        new_wavels[-1] = bandws[1]
        start = n.where(bandws[0] < wavels)[0][0]
        end = n.where(bandws[1] > wavels)[0][-1]
        #datacube = datacube[start:end+1,:,:]

    elif wavels[-1] < bandws[
            1]:  #cube longest wavelength shorter than grating longest wavelength
        print 'Cube longest wavelength shorter than grating'

        new_wavels = n.arange(bandws[0], wavels[-1] + lamb_per_pix / 2.,
                              lamb_per_pix)
        new_wavels[-1] = wavels[-1]
        start = n.where(bandws[0] < wavels)[0][0]
        end = n.where(bandws[1] > wavels)[0][-1]
        #datacube = datacube[start:end+1,:,:]

    else:
        raise ValueError('Specres wavelength error!!!')

    #####

    new_cube = n.zeros((len(new_wavels), y, x), dtype=float)

    ###New 30-05-14
    #Put datacube flux into photon units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head[
            'FUNITS'] == 'J/s/m2/A/arcsec2':
        datacube *= (head['CDELT3'] * 10000.)
    else:
        datacube *= head['CDELT3']

    #print 'Datacube sum = ', datacube.sum()

    #Bin up in spectral dimension to new pixel sampling
    #Iterate over x-axis and use frebin function on 2D y-z arrays
    for i in xrange(x):
        new_cube[:, :, i] = frebin(datacube[start:end + 1, :, i],
                                   (y, len(new_wavels)), True)

    #print 'New cube sum = ', new_cube.sum()

    #Put datacube flux back into photons/wavelength units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head[
            'FUNITS'] == 'J/s/m2/A/arcsec2':
        new_cube /= (lamb_per_pix * 10000.)
    else:
        new_cube /= lamb_per_pix

    #Update header
    head['CRVAL3'] = new_wavels[0]
    head['CDELT3'] = (new_wavels[1] - new_wavels[0])
    head['NAXIS3'] = len(new_wavels)
    head['SPECRES'] = new_res

    resol = n.round(new_wavels[len(new_wavels) / 2] / bandws[2], 0)

    print 'Spectral resolution and wavelength range - done!'

    #Return new_datacube, new_wavels, updated_header
    return new_cube, head, new_wavels, new_res, lamb_per_pix, resol
示例#13
0
def spectral_res(datacube,
                 head,
                 R,
                 band,
                 wavels,
                 spec_nyquist=True,
                 spec_samp=1.):
    '''Function that takes input datacube and rebins it to the
    chosen spectral resolution. It convolves datacube along wavelength
    axis, interpolates all spaxels along wavelength axis then extracts
    pixel vales for each datacube wavelength channel. Function combines both
    spectral resolution choice and datacube chopping in wavelength axis.
    Option of bypassing spectral processing by setting band=='None' and
    spec_nyquist=True - this ignores wavelength dimension.

    Inputs:
        datacube: object datacube
        head: header file for object datacube
        R: spectral resolving power
        band: string representing wavelength band choice.
              Option of "None" which ignores photometric bands. 
        wavels: wavelength array for datacube
        spec_nyquist: Boolean - if True, 2 pixels per resolution element.
                              - if False, uses spec_samp value

    Outputs:
        scaled_cube: rebinned datacube
        head: updated header file
        new_wavels: new wavelength array for datacube
        delta_lambda: New resolution [um]
        lamb_per_pix: pixel dispersion [um/pixel]
    '''

    print 'Spectral resolution and wavelength range.'
    print 'Chosen resolution: ', R
    print 'Chosen band: ', band

    bands = {
        'V': (.47, .63),
        'R': (.63, .79),
        'Iz': (.82, 1.03),
        'J': (1.08, 1.36),
        'H': (1.46, 1.83),
        'K': (1.95, 2.45),
        'V+R': (.47, .81),
        'Iz+J': (.8, 1.36),
        'H+K': (1.45, 2.45),
        'V-high': (.53, .59),
        'R-high': (.61, .68),
        'z': (.82, .91),
        'J-high': (1.17, 1.29),
        'H-high': (1.545, 1.715),
        'K-high': (2.09, 2.32),
        'None': None
    }

    bandws = bands[band]

    z, y, x = datacube.shape

    if bandws == None and spec_nyquist == False:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3']
    elif bandws != None and spec_nyquist == True:
        new_res = (bandws[0] + bandws[1]) / (2. * R)
        lamb_per_pix = new_res / 2.
    elif bandws != None and spec_nyquist == False:
        new_res = (bandws[0] + bandws[1]) / (2. * R)
        lamb_per_pix = spec_samp / 10000.
    elif bandws == None and spec_nyquist == True:
        #no convolution, just interpolate and read out new wavelengths
        #when sig=0, gauss returns [1.,1.] so convolution does nothing.
        #        new_res = head['SPECRES']
        new_res = (wavels[0] + wavels[-1]) / (2. * R)
        lamb_per_pix = new_res / 2.
    else:
        print 'Ignoring spectral dimension!'
        return datacube, head, wavels, head['SPECRES'], head['CDELT3']

    print 'Current resolution = %.5f microns' % head['SPECRES']
    print 'Current sampling = %.5f microns' % head['CDELT3']
    print 'New resolution = %.5f microns' % new_res
    print 'New sampling = %.5f microns' % lamb_per_pix

    if head['SPECRES'] >= new_res:
        print 'WARNING: Input spectral resolution is coarser (or equal) than chosen output!'
        #Chose whether to convolve with LSF or simply resample.
        condition = raw_input(
            'Do you want to convolve with Gaussian LSF of FWHM'
            ' given by band and chosen resolving power [y], or not [any other key]?: '
        )

        if condition == 'y':
            print 'Convolving with LSF'
            #Generate Gaussian LSF of FWHM = (bandws[0]+bandws[1])/(2.*R)
            sig = new_res / (2. * n.sqrt(2. * n.log(2.)))
            gauss_array = Gauss(sig, head['CDELT3'])
            #Convolve datacube array with Gaussian along wavelength axis
            datacube = convolve1d(datacube, gauss_array[:, 1], axis=0)

    else:
        print 'Input spectral resolution smaller than chosen output.'
        print 'Convolving with corresponding LSF.'
        #Generate Gaussian LSF of FWHM = sqrt(new_resolution**2-head['SPECRES']**2)
        sig = n.sqrt(new_res**2 -
                     head['SPECRES']**2) / (2. * n.sqrt(2. * n.log(2.)))
        gauss_array = Gauss(sig, head['CDELT3'])

        #Convolve datacube array with Gaussian along wavelength axis
        datacube = convolve1d(datacube, gauss_array[:, 1], axis=0)

    #New wavelength values from chosen photometric band (or ignore)
    if bandws:
        new_wavels = n.arange(bandws[0], bandws[1], lamb_per_pix)
        new_wavels[-1] = bandws[1]
        #Slice datacube down to size of new wavelength array
        start = n.where(wavels < new_wavels[0])[0][-1]
        end = n.where(wavels > new_wavels[-1])[0][0]
        datacube = datacube[start:end + 1, :, :]
    elif not bandws:
        new_wavels = n.arange(wavels[0], wavels[-1], lamb_per_pix)
        new_wavels[-1] = wavels[-1]

    new_cube = n.zeros((len(new_wavels), y, x), dtype=float)

    ###New 30-05-14
    #Put datacube flux into photon units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head[
            'FUNITS'] == 'J/s/m2/A/arcsec2':
        datacube *= (head['CDELT3'] * 10000.)
    else:
        datacube *= head['CDELT3']

    #print 'Datacube sum = ', datacube.sum()

    #Bin up in spectral dimension to new pixel sampling
    #Iterate over x-axis and use frebin function on 2D y-z arrays
    for i in xrange(x):
        new_cube[:, :, i] = frebin(datacube[:, :, i], (y, len(new_wavels)),
                                   True)

    #print 'New cube sum = ', new_cube.sum()

    #Put datacube flux back into photons/wavelength units
    if head['FUNITS'] == 'erg/s/cm2/A/arcsec2' or head[
            'FUNITS'] == 'J/s/m2/A/arcsec2':
        new_cube /= (lamb_per_pix * 10000.)
    else:
        new_cube /= lamb_per_pix

    #Update header
    head.update('CRVAL3', new_wavels[0])
    head.update('CDELT3', (new_wavels[1] - new_wavels[0]))
    head.update('NAXIS3', len(new_wavels))
    head.update('SPECRES', new_res)

    print 'Spectral resolution and wavelength range - done!'

    #Return new_datacube, new_wavels, updated_header
    return new_cube, head, new_wavels, new_res, lamb_per_pix