Exemple #1
0
 def testobsband(self):
     self.bp = S.ObsBandpass('acs,hrc,f555w')
     tst = self.bp(3000)
     assert True
Exemple #2
0
    # Unset the *CAM thruput stuff
    S.setref(comptable=None,
             graphtable=None)  # leave the telescope area as it was
    S.setref(area=None)  # reset the telescope area as well

    # Synthetic spectrum
    sp = S.FileSpectrum(os.path.join(pickles_path, name + '.fits'))

    # Apply extinction to that spectrum
    ext = S.Extinction(ebv, 'gal3')
    sp = sp * ext

    # Get all the magnitudes
    simulated_mags = {}
    for f in sdss_filters:
        bp = S.ObsBandpass("{},{}".format('sdss', f))
        obs = S.Observation(sp, bp, force='taper')
        mag = obs.effstim("abmag")
        simulated_mags[f] = mag

    # Get the actual colours
    for colour in SDSS_COLOURS:
        f1, f2 = colour.split("-")
        colour_mag = simulated_mags[f1] - simulated_mags[f2]

        row[colour] = colour_mag

    # Get the colour corrections for the super filters
    S.setref(**getref(telescope))

    for f in cam_filters:
    def test_wfpc2_cont(self):
        bp = S.ObsBandpass('wfpc2,1,a2d7,f300w,cont#49892.0')
        ur = bp.unit_response()

        self.assertApproxFP(ur, 6.3011E-17, accuracy=1.e-4)
Exemple #4
0
    #       bandlistfile = c['BANDS']
    #       bandnames,bands = readbands(bandlistfile)
    #   except:
    #       band = c['BAND']
    #       a = band.split(',')
    #       bandnames = [a[-1]]
    #       bands = [S.ObsBandpass(band)]
    try:
        redshifts = array(c['REDSHIFTS'])
    except:
        z = c['REDSHIFT_RANGE']
        redshifts = arange(z[0], z[1], z[2])
    if c.has_key('NORM_BAND'):
        normbandlist = c['NORM_BAND']
        normbandstring = ','.join(normbandlist)
        normband = S.ObsBandpass(normbandstring)
        normvalue = c['NORM_ABMAG']
        normredshift = c['NORM_REDSHIFT']
        norm = [normband, normvalue, normredshift]
#       print norm
    else:
        norm = []
    # Get cosmological parameters
    H0 = 70.
    omega_tot = 1.0
    omega_m = 0.27
    omega_l = 0.73
    if c.has_key('H0'): H0 = c['H0']
    if c.has_key('Omega_tot'): omega_tot = c['Omega_tot']
    if c.has_key('Omega_m'): omega_m = c['Omega_m']
    if c.has_key('Omega_lambda'): omega_l = c['Omega_lambda']
Exemple #5
0
    'F160W': 15369.175708965562,
    'F435W': 4328.256914042873,
    'F606W': 5921.658489236346,
    'F775W': 7693.297933335407,
    'F814W': 8058.784799323767,
    'VISTAH': 1.6433e+04
}

if False:
    import pysynphot as S
    n = 1.e-20
    spec = S.FlatSpectrum(n, fluxunits='flam')
    photflam = {}
    photplam = {}
    for filter in ['F098M', 'F105W', 'F110W', 'F125W', 'F140W', 'F160W']:
        bp = S.ObsBandpass('wfc3,ir,%s' % (filter.lower()))
        photplam[filter] = bp.pivot()
        obs = S.Observation(spec, bp)
        photflam[filter] = n / obs.countrate()

    #
    for filter in ['F435W', 'F606W', 'F775W', 'F814W']:
        bp = S.ObsBandpass('acs,wfc1,%s' % (filter.lower()))
        photplam[filter] = bp.pivot()
        obs = S.Observation(spec, bp)
        photflam[filter] = n / obs.countrate()


class GrismFLT(object):
    """
    Scripts for simple modeling of individual grism FLT images
Exemple #6
0
def get_pbmodel(pbnames, model, pbfile=None, mag_type=None, mag_zero=0.):
    """
    Converts passband names ``pbnames`` into passband models based on the
    mapping of name to ``pysynphot`` ``obsmode`` strings in ``pbfile``.

    Parameters
    ----------
    pbnames : array-like
        List of passband names to get throughput models for Each name is
        resolved by first looking in ``pbfile`` (if provided) If an entry is
        found, that entry is treated as an ``obsmode`` for pysynphot. If the
        entry cannot be treated as an ``obsmode,`` we attempt to treat as an
        ASCII file. If neither is possible, an error is raised.
    model : :py:class:`WDmodel.WDmodel.WDmodel` instance
        The DA White Dwarf SED model generator
        All the passbands are interpolated onto the wavelengths of the SED
        model.
    pbfile : str, optional
        Filename containing mapping between ``pbnames`` and ``pysynphot``
        ``obsmode`` string, as well as the standard that has 0 magnitude in the
        system (either ''Vega'' or ''AB''). The ``obsmode`` may also be the
        fullpath to a file that is readable by ``pysynphot``
    mag_type : str, optional
        One of ''vegamag'' or ''abmag''
        Used to specify the standard that has mag_zero magnitude in the passband.
        If ``magsys`` is specified in ``pbfile,`` that overrides this option.
        Must be the same for all passbands listed in ``pbname`` that do not
        have ``magsys`` specified in ``pbfile``
        If ``pbnames`` require multiple ``mag_type``, concatentate the output.
    mag_zero : float, optional
        Magnitude of the standard in the passband
        If ``magzero`` is specified in ``pbfile,`` that overrides this option.
        Must be the same for all passbands listed in ``pbname`` that do not
        have ``magzero`` specified in ``pbfile``
        If ``pbnames`` require multiple ``mag_zero``, concatentate the output.

    Returns
    -------
    out : dict
        Output passband model dictionary. Has passband name ``pb`` from ``pbnames`` as key.

    Raises
    ------
    RuntimeError
        If a bandpass cannot be loaded

    Notes
    -----
        Each item of ``out`` is a tuple with
            * ``pb`` : (:py:class:`numpy.recarray`)
              The passband transmission with zero throughput entries trimmed.
              Has ``dtype=[('wave', '<f8'), ('throughput', '<f8')]``
            * ``transmission`` : (array-like)
              The non-zero passband transmission interpolated onto overlapping model wavelengths
            * ``ind`` : (array-like)
              Indices of model wavelength that overlap with this passband
            * ``zp`` : (float)
              mag_type zeropoint of this passband
            * ``avgwave`` : (float)
              Passband average/reference wavelength

        ``pbfile`` must be readable by :py:func:`WDmodel.io.read_pbmap` and
        must return a :py:class:`numpy.recarray`
        with``dtype=[('pb', 'str'),('obsmode', 'str')]``

        If there is no entry in ``pbfile`` for a passband, then we attempt to
        use the passband name ``pb`` as ``obsmode`` string as is.

        Trims the bandpass to entries with non-zero transmission and determines
        the ``VEGAMAG/ABMAG`` zeropoint for the passband - i.e. ``zp`` that
        gives ``mag_Vega/AB=mag_zero`` in all passbands.

    See Also
    --------
    :py:func:`WDmodel.io.read_pbmap`
    :py:func:`WDmodel.passband.chop_syn_spec_pb`
    """

    # figure out the mapping from passband to observation mode
    if pbfile is None:
        pbfile = 'WDmodel_pb_obsmode_map.txt'
        pbfile = io.get_pkgfile(pbfile)
    pbdata  = io.read_pbmap(pbfile)
    pbmap   = dict(list(zip(pbdata.pb, pbdata.obsmode)))
    sysmap  = dict(list(zip(pbdata.pb, pbdata.magsys)))
    zeromap = dict(list(zip(pbdata.pb, pbdata.magzero)))

    # setup the photometric system by defining the standard and corresponding magnitude system
    if mag_type not in ('vegamag', 'abmag', None):
        message = 'Magnitude system must be one of abmag or vegamag'
        raise RuntimeError(message)

    try:
        mag_zero = float(mag_zero)
    except ValueError as e:
        message = 'Zero magnitude must be a floating point number'
        raise RuntimeError(message)

    # define the standards
    vega = S.Vega
    vega.convert('flam')
    ab   = S.FlatSpectrum(0., waveunits='angstrom', fluxunits='abmag')
    ab.convert('flam')

    # defile the magnitude sysem
    if mag_type == 'vegamag':
        mag_type= 'vegamag'
    else:
        mag_type = 'abmag'

    out = OrderedDict()

    for pb in pbnames:

        standard = None

        # load each passband
        obsmode = pbmap.get(pb, pb)
        magsys  = sysmap.get(pb, mag_type)
        synphot_mag = zeromap.get(pb, mag_zero)

        if magsys == 'vegamag':
            standard = vega
        elif magsys == 'abmag':
            standard = ab
        else:
            message = 'Unknown standard system {} for passband {}'.format(magsys, pb)
            raise RuntimeError(message)

        loadedpb = False
        # treat the passband as a obsmode string
        try:
            bp = S.ObsBandpass(obsmode)
            loadedpb = True
        except ValueError:
            message = 'Could not load pb {} as an obsmode string {}'.format(pb, obsmode)
            warnings.warn(message, RuntimeWarning)
            loadedpb = False

        # if that fails, try to load the passband interpreting obsmode as a file
        if not loadedpb:
            try:
                bandpassfile = io.get_filepath(obsmode)
                bp = S.FileBandpass(bandpassfile)
                loadedpb = True
            except Exception as e:
                message = 'Could not load passband {} from obsmode or file {}'.format(pb, obsmode)
                warnings.warn(message, RuntimeWarning)
                loadedpb = False

        if not loadedpb:
            message = 'Could not load passband {}. Giving up.'.format(pb)
            raise RuntimeError(message)

        avgwave = bp.avgwave()
        if standard.wave.min() > model._wave.min():
            message = 'Standard does not extend past the blue edge of the model'
            warnings.warn(message, RuntimeWarning)

        if standard.wave.max() < model._wave.max():
            message = 'Standard does not extend past the red edge of the model'
            warnings.warn(message, RuntimeWarning)

        # interpolate the standard onto the model wavelengths
        sinterp = interp1d(standard.wave, standard.flux, fill_value='extrapolate')
        standard_flux = sinterp(model._wave)
        standard = np.rec.fromarrays([model._wave, standard_flux], names='wave,flux')

        # cut the passband to non-zero values and interpolate onto overlapping standard wavelengths
        outpb, outzp = chop_syn_spec_pb(standard, synphot_mag, bp, model)

        # interpolate the passband onto the standard's  wavelengths
        transmission, ind = interp_passband(model._wave, outpb, model)

        # save everything we need for this passband
        out[pb] = (outpb, transmission, ind, outzp, avgwave)
    return out
Exemple #7
0
 def setUp(self):
     self.sp=S.ObsBandpass('acs,hrc,f555w')
Exemple #8
0
#redden the spectrum  using Cardelli 1989, RV=3.1
E_BmV = [0.0, 0.4, 0.6, 0.8, 1.0, 1.3, 1.5, 2.0]
for e in E_BmV:

	print 'E(B-V):', e
	red_spectrum = spectrum *  S.Extinction(e, 'mwavg')
	
	#plt.figure()
	#plt.plot(red_spectrum.wave, red_spectrum.flux)
	#plt.xlabel(red_spectrum.waveunits)
	#plt.ylabel(red_spectrum.fluxunits)
	#plt.xlim(3000, 10000)
	#plt.ylim(0, 0.6e10)
	#plt.show()
		
	obs_U = S.Observation(red_spectrum, S.ObsBandpass('U'))
	obs_B = S.Observation(red_spectrum, S.ObsBandpass('B'))
	obs_V = S.Observation(red_spectrum, S.ObsBandpass('V'))
	obs_I = S.Observation(red_spectrum, S.ObsBandpass('I'))


	
	U_min_B = obs_U.effstim(magsystem) - obs_B.effstim(magsystem)
	B_min_V = obs_B.effstim(magsystem) - obs_V.effstim(magsystem)
	V_min_I = obs_V.effstim(magsystem) - obs_I.effstim(magsystem)
	

	#paper1: corrections that were supposed to be applied	
	B_min_V+=0.010
	V_min_I-=0.002
	
Exemple #9
0
#!/usr/bin/env python

from numpy import *
from pygoods import *
import pysynphot as S
import magredshift as MR
from pysynphot import Extinction
import myutil
import arrayspec as A
import simutil

Lsun = 3.826e33  # erg / sec
pc_cm = 30.857e17  # 1 parsec in cm
#uni1500 = S.FileBandpass('uni1500.bp')
uni1500 = S.Box(1500., 100.)
iband = S.ObsBandpass('acs,wfc2,f775w')
zband = S.ObsBandpass('acs,wfc2,f850lp')
#sp10 = S.FileSpectrum('mylbg_sfr10.sed')


def simkcorr(sp, absmag_rest, restband, obsband, z, lya_ew):
    # defined as m_1 = M_2 + kcorr
    # m_1: apparent magnitude in observed band
    # M_2: absolute magnitude in rest-frame band
    # assumes BC03 model: model flux unit is in L_solar/angstrom
    #sp = S.FileSpectrum(spec)
    tenpc = 4. * pi * (10. * pc_cm)**2  # 10 parsec in centimeter
    absmag = A.ABmag(sp, restband)
    spn = sp * 10.**(
        (absmag_rest - absmag) / -2.5)  # normalize sp to absmag_rest
    spn = spn * tenpc  # get luminosity
Exemple #10
0
    # create pysynphot spectrum
    sp = S.ArraySpectrum(
        koester_spectrum['WAVELENGTH (ANGSTROM)'],
        koester_spectrum['FLUX (ERG/CM2/S/A)'],
        fluxunits='flam',
        waveunits='Angstroms'
    )

    # Set the lightpath for the hcam observations
    S.setref(**getref(hcam_tel))

    # Get all the hcam magnitudes
    simulated_mags = {}
    for f in hcam_filters:
        bp = S.ObsBandpass("{},{},{}".format('hcam',hcam_tel, f))
        obs = S.Observation(sp, bp, force='taper')
        mag = obs.effstim("abmag")
        simulated_mags['hcam_{}'.format(f)] = mag

    # Get the actual colours
    for colour in SDSS_COLOURS:
        f1, f2 = colour.split("-")
        colour_mag = simulated_mags["hcam_{}".format(f1)] - simulated_mags["hcam_{}".format(f2)]

        row[colour] = colour_mag

    # Magnitudes
    for f in ucam_filters:
        bp = S.ObsBandpass("{},{},{}".format(ucam_tel,'ucam',f))
        obs = S.Observation(sp, bp, force='taper')
Exemple #11
0
 def makebp(mode):
     try:
         bp = S.ObsBandpass(mode)
     except KeyError as e:
         raise AssertionError(e.message)
Exemple #12
0
def uvj_diagram(u='galaxy_u.fits',
                v='galaxy_v.fits',
                j='galaxy_j.fits',
                target='galaxy',
                file_name='galaxy*.fits',
                size=200,
                x0=1000,
                y0=1000):
    """
    Function for plotting a spatially resolved UVJ Diagram of an input target, 
    while comparing with EAZY templates.
    
    INPUTS:
            u: Fits file of the image in the U band.
            v: Fits file of the image in the V band.
            j: Fits file of the image in the J band.
       target: The name of the target, to be used in the output files.
    file_name: General form of the file names that contain the UVJ images.
         size: Size of the slice to plot only part of the original image.
           x0: Center of the x-coordinate of the slice.
           y0: Center of the y-coordinate of the slice.
        
    KEYWORDS:
          PLOT: Set this keyword to plot the UVJ diagram.
    OUTPUTS:
          Plot of the UVJ diagram.
    """

    from grizli import utils
    import numpy as np
    import astropy.io.fits as pyfits
    import matplotlib.pyplot as plt
    import glob
    import pysynphot as S

    slx = slice(x0 - size, x0 + size)
    sly = slice(y0 - size, y0 + size)

    u_im = pyfits.open(u)
    v_im = pyfits.open(v)
    j_im = pyfits.open(j)

    for ext in [0, 1]:
        if 'PHOTPLAM' in u_im[ext].header:
            u_lam = u_im[ext].header['PHOTPLAM']
            break
    for ext in [0, 1]:
        if 'PHOTPLAM' in v_im[ext].header:
            v_lam = v_im[ext].header['PHOTPLAM']
            break
    for ext in [0, 1]:
        if 'PHOTPLAM' in j_im[ext].header:
            j_lam = j_im[ext].header['PHOTPLAM']
            break

    fu = u_im['SCI'].data[sly, slx] * u_im[1].header['IM2FLAM'] * (u_lam**2)
    fv = v_im['SCI'].data[sly, slx] * v_im[1].header['IM2FLAM'] * (v_lam**2)
    fj = j_im['SCI'].data[sly, slx] * j_im[1].header['IM2FLAM'] * (j_lam**2)

    fu_error = u_im['ERR'].data[sly, slx] * u_im[1].header['IM2FLAM'] * (u_lam
                                                                         **2)
    fv_error = v_im['ERR'].data[sly, slx] * v_im[1].header['IM2FLAM'] * (v_lam
                                                                         **2)
    fj_error = j_im['ERR'].data[sly, slx] * j_im[1].header['IM2FLAM'] * (j_lam
                                                                         **2)

    u_v_err = (2.5 / np.log(10)) * np.sqrt((fu_error / fu)**2 +
                                           (fv_error / fv)**2)
    v_j_err = (2.5 / np.log(10)) * np.sqrt((fj_error / fj)**2 +
                                           (fv_error / fv)**2)

    u_v = -2.5 * np.log10(fu / fv)
    v_j = -2.5 * np.log10(fv / fj)

    mask = (u_v_err < 0.1) & (v_j_err < 0.1)

    templ = utils.load_templates(full_line_list=[],
                                 line_complexes=False,
                                 fsps_templates=True,
                                 alf_template=True)

    files = glob.glob(file_name)
    files.sort()
    images = {}
    bandpasses = {}

    for file in files:
        im = pyfits.open(file)
        filt = utils.get_hst_filter(im[0].header)
        for ext in [0, 1]:
            if 'PHOTMODE' in im[ext].header:
                bandpasses[filt.lower()] = S.ObsBandpass(
                    im[ext].header['PHOTMODE'].replace(' ', ','))
                break
        images[filt.lower()] = im['SCI'].data

    template_fluxes = {}
    for f in bandpasses:
        template_fluxes[f] = np.zeros(len(templ))

    # templates from EAZY
    for i, t in enumerate(templ):
        t_z = templ[t].zscale(0.03)
        for f in bandpasses:
            template_fluxes[f][i] = t_z.integrate_filter(bandpasses[f])

    s = templ.keys()
    uv = -2.5 * np.log10(template_fluxes[u] / template_fluxes[v])
    vj = -2.5 * np.log10(template_fluxes[v] / template_fluxes[j])

    fig, ax = plt.subplots(figsize=(12, 10))

    plt.plot(v_j[mask], u_v[mask], 'kx', ms=1, zorder=-5)

    for i, lab in enumerate(s):
        plt.scatter(vj[i], uv[i], label=lab)

    box = ax.get_position()
    ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
    ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

    plt.xlabel('V-J [observed] (AB mag)'.format(v, j))
    plt.ylabel('U-V [observed] (AB mag)'.format(u, v))
    plt.title('UVJ Diagram {0}'.format(target))
    plt.show()


#-----------------------------------------------------------------------------
Exemple #13
0
def subtract_continuum(line='f673n',
                       cont='f814w',
                       target='galaxy',
                       file_name='galaxy*.fits',
                       line_name='ha',
                       z=0.02,
                       plot=False):
    """
    Function for subtracting the continuum in a line emission image

    INPUTS:
         line: Filter into which the emission line falls.
         cont: Filter within which the emission line and broader continuum are contained.
       target: The name of the target, to be used in the output files.
    file_name: General form of the file names that contain the line and continuum images.
    line_name: State 'ha' or 'pab' to subtract Balmer-alpha or Paschen-beta respectively.
            z: Redshift of the target object.
       
    KEYWORDS:
         PLOT: Set this keyword to produce a plot of the two-dimensional
               continuum subtracted image.   
    OUTPUTS:
         Fits file with the continuum subtracted line emission image.

    """

    import pysynphot as S
    import numpy as np
    import glob
    from grizli import utils
    import astropy.io.fits as pyfits
    import matplotlib.pyplot as plt

    # restframe wavelength of the emission lines to subtract
    wave_pab = 1.2822e4
    wave_ha = 6562.8

    print('Target =', target)
    files = glob.glob(file_name)
    files.sort()
    images = {}
    headers = {}
    bandpasses = {}

    for file in files:
        im = pyfits.open(file)
        filt = utils.get_hst_filter(im[0].header).lower()
        for ext in [0, 1]:
            if 'PHOTMODE' in im[ext].header:
                photflam = im[ext].header['PHOTFLAM']
                headers[filt.lower()] = im[ext].header
                bandpasses[filt.lower()] = S.ObsBandpass(
                    im[ext].header['PHOTMODE'].replace(' ', ','))
                break

        flat_flam = S.FlatSpectrum(1., fluxunits='flam')
        obs = S.Observation(flat_flam, bandpasses[filt.lower()])
        my_photflam = 1 / obs.countrate()
        flat_ujy = S.FlatSpectrum(1, fluxunits='ujy')
        obs = S.Observation(flat_ujy, bandpasses[filt.lower()])
        my_photfnu = 1 / obs.countrate()
        images[filt.lower()] = [im['SCI'].data, im['ERR'].data]

    # Use PySynphot to compute flux calibration factors

    if line_name == 'pab':
        # Pa-beta
        cont_filter, line_filter, line_wave, name = cont, line, wave_pab, 'pab'
    elif line_name == 'ha':
        # H-alpha
        cont_filter, line_filter, line_wave, name = cont, line, wave_ha, 'ha'

    ################
    # Continuum - flat spectrum
    cont = S.FlatSpectrum(1.e-19, fluxunits='flam')

    ###############
    # Continuum - slope spectrum
    cont_wave = np.arange(1000, 2.e4)

    slope = 0  # flat
    slope = 1  # red slope, increasing toward longer wavelengths
    cont_flux = (cont_wave / 1.e4)**slope
    cont = S.ArraySpectrum(cont_wave, cont_flux, fluxunits='flam')

    ################
    # Continuum, galaxy model
    templ = utils.load_templates(full_line_list=[],
                                 line_complexes=False,
                                 alf_template=True)['alf_SSP.dat']
    cont = S.ArraySpectrum(templ.wave * (1 + z), templ.flux, fluxunits='flam')

    # Gaussian line model
    ref_flux = 1.e-17
    line_model = S.GaussianSource(ref_flux,
                                  line_wave * (1 + z),
                                  10,
                                  waveunits='angstrom',
                                  fluxunits='flam')

    cont_contin_countrate = S.Observation(cont,
                                          bandpasses[cont_filter]).countrate()
    line_contin_countrate = S.Observation(cont,
                                          bandpasses[line_filter]).countrate()
    line_emline_countrate = S.Observation(line_model,
                                          bandpasses[line_filter]).countrate()

    # Continuum-subtracted, flux-calibrated
    line_calib = (
        images[line_filter][0] -
        images[cont_filter][0] * line_contin_countrate / cont_contin_countrate)
    line_calib /= line_emline_countrate

    # Propagated error of the subtraction
    err_sub = np.sqrt((images[line_filter][1]**2) +
                      (images[cont_filter][1] * line_contin_countrate /
                       cont_contin_countrate)**2)
    err_sub /= line_emline_countrate

    if plot:
        print("Continuum subtracted image")
        plt.figure()
        plt.imshow(line_calib, vmin=-0.5, vmax=0.5)
        plt.colorbar()

    primary_extn = pyfits.PrimaryHDU()
    sci_extn = pyfits.ImageHDU(data=line_calib, name='SCI')
    err_extn = pyfits.ImageHDU(data=err_sub, name='ERR')
    hdul = pyfits.HDUList([primary_extn, sci_extn, err_extn])
    hdul.writeto('sub_{0}_{1}.fits'.format(line_name, target),
                 output_verify='fix',
                 overwrite=True)

    print(line_name, ' Continuum Subtracted')
Exemple #14
0
 def test_c1280(self):
     self.obsmode = 'cos,fuv,g140l,c1280'
     self.tda['obsmode'] = self.obsmode
     bp = S.ObsBandpass(self.obsmode)
     obs = S.Observation(S.BlackBody(5500), bp)
Exemple #15
0
def get_col_correction(telescope, instrument, filter, teff, logg, plot=False):
    S.setref(**getref(telescope))
    bp = S.ObsBandpass('{},{},{}'.format(telescope, instrument, filter))
    bp_HCAM_GTC = S.ObsBandpass(
        'hcam,gtc,{}'.format(filter.split('_')[0] + '_s'))

    table_fname = get_fname(teff, logg)
    teff, logg = get_teff_logg(table_fname)
    table = pd.read_csv(table_fname,
                        delim_whitespace=True,
                        comment='#',
                        names=['WAVELENGTH (ANGSTROM)', 'FLUX (ERG/CM2/S/A)'])

    # drop duplicate wavelengths. WTF are they here Koester?
    table.drop_duplicates(subset='WAVELENGTH (ANGSTROM)', inplace=True)

    # create pysynphot spectrum
    sp = S.ArraySpectrum(table['WAVELENGTH (ANGSTROM)'],
                         table['FLUX (ERG/CM2/S/A)'],
                         fluxunits='flam',
                         waveunits='Angstrom')
    obs = S.Observation(sp, bp, force='taper')
    obs_HCAM_GTC = S.Observation(sp, bp_HCAM_GTC, force='taper')
    tot_mag = obs.effstim('abmag')

    col_term = obs_HCAM_GTC.effstim('abmag') - tot_mag

    if plot:
        # Plotting stuff
        limits = (bp.wave.min(), bp.wave.max())
        cut_table = table[(table['WAVELENGTH (ANGSTROM)'] < limits[1])
                          & (table['WAVELENGTH (ANGSTROM)'] > limits[0])]

        fig, ax = plt.subplots()
        ax2 = ax.twinx()

        ax2.plot(bp.wave,
                 bp.throughput,
                 color='red',
                 linestyle='--',
                 label='{}, {} Throughput'.format(instrument, telescope))
        ax2.plot(bp_HCAM_GTC.wave,
                 bp_HCAM_GTC.throughput,
                 color='black',
                 linestyle='--',
                 label='HCAM, GTC Throughput')
        ax.plot(obs.wave,
                obs.flux,
                color='red',
                label='{}, {} stimulation'.format(instrument, telescope))
        ax.plot(obs_HCAM_GTC.wave,
                obs_HCAM_GTC.flux,
                color='black',
                label='HCAM, GTC stimulation')
        ax.step(cut_table['WAVELENGTH (ANGSTROM)'],
                cut_table['FLUX (ERG/CM2/S/A)'],
                color='lightgrey',
                label='Raw Spectrum')

        ax.set_title(
            "Teff: {} || log(g): {} || detected magnitude: {:.3f} || Color {:.3f}"
            .format(teff, logg, tot_mag, col_term))
        ax.set_xlabel("Wavelength, Angstroms")
        ax.set_ylabel("Flux, erg/cm2/s/A")
        ax.set_xlim(limits)
        fig.legend()
        plt.tight_layout()

        plt.show()

    return col_term
Exemple #16
0
def apply_binning(tab_file, seg_file, mask_file, obj_name):
    
    """
    Function to bin images according to the input "seg_file", obtained with Voronoi_Binning
    
    Input for this function is the output from the Voronoi_Binning function.
    
    """
    
    import glob
    import astropy.units.astrophys as u
    import numpy as np
    import astropy.io.fits as pyfits
    from grizli import utils
    import pysynphot as S
    
    files = glob.glob('*{0}*fits.gz'.format(obj_name))
    files.sort()
    res = {}
    master_table = tab_file
    bandpasses = {}
    h = {}
    
    for file in files:
        im = pyfits.open(file)
        filt = utils.get_hst_filter(im[0].header)
        for ext in [0,1]:
            if 'PHOTMODE' in im[ext].header:
                bandpasses[filt.lower()] = S.ObsBandpass(im[ext].header['PHOTMODE'].replace(' ',','))
                break    
        flat_flam = S.FlatSpectrum(1., fluxunits='flam')
        obs = S.Observation(flat_flam, bandpasses[filt.lower()])
        my_photflam = 1/obs.countrate()
        flat_ujy = S.FlatSpectrum(1, fluxunits='ujy')
        obs = S.Observation(flat_ujy, bandpasses[filt.lower()])
        my_photfnu = 1/obs.countrate()
        h['{0}_photfnu'.format(filt.lower())] = my_photfnu
        h['{0}_photflam'.format(filt.lower())] = my_photflam
    
    for file in files:
        im = pyfits.open(file)
        f = utils.get_hst_filter(im[0].header).lower()
        im2mujy =  h['{0}_photfnu'.format(f)]
        im2flam =  h['{0}_photflam'.format(f)]
        print(f,im2mujy,im2flam)
        res[f],data_tab = bin_image(im, tab_file, seg_file, mask_file)
        
        primary_extn = pyfits.PrimaryHDU()
        sci_extn = pyfits.ImageHDU(data=res[f]['image_flux'].astype(np.float32),name='SCI')
        err_extn = pyfits.ImageHDU(data=res[f]['image_err'].astype(np.float32),name='ERR')
        hdul = pyfits.HDUList([primary_extn, sci_extn, err_extn])
        for ext in [0,1]:
            for k in im[ext].header:
                if k not in hdul[ext].header:
                    if k in ['COMMENT','HISTORY','']:
                        continue
                    hdul[ext].header[k] = im[ext].header[k]
        hdul[1].header['IM2FLAM'] = (im2flam, 'Convert images to flambda cgs')
        hdul[1].header['IM2MUJY'] = (im2mujy, 'Convert images to fnu, microJy')
        hdul.writeto('binned_{0}_{1}_image.fits'.format(obj_name,f), output_verify='fix',overwrite=True)
        
        # bin_flux and bin_error of each filter to append to the master table       
        master_table['{0}_flux'.format(f)] = res[f]['bin_flux']*im2mujy
        master_table['{0}_flux'.format(f)].unit = u.Jy*1e-6
        master_table['{0}_err'.format(f)] = res[f]['bin_err']*im2mujy
        master_table['{0}_err'.format(f)].unit = u.Jy*1e-6

    # master_table.remove_columns(['flux','err','area'])
    master_table.write('binned_{0}_master_table.fits'.format(obj_name), overwrite=True)
    
    return master_table
Exemple #17
0
 def bandpass(self):
     import pysynphot as ps
     ps.setref(**self.REFS)
     obsmode = "wfc3,ir," + self.filter.lower()
     return ps.ObsBandpass(obsmode)
Exemple #18
0
def read_passband(pb, pbzp=None):
    """
    Read a passband.


    Parameters
    ----------
    pb : str
        pysynphot obsmode or obsmode listed in `pbzptmag.txt`
    pbzp : float, optional
        AB magnitude zeropoint of the passband

    Returns
    -------
    pb : :py:class:`pysynphot.ArrayBandpass` or :py:class:`pysynphot.obsbandpass.ObsModeBandpass`
        The passband data.
        Has ``dtype=[('wave', '<f8'), ('throughput', '<f8')]``
    pbzp : float
        passband AB zeropoint - potentially NaN if this was not supplied. If NaN
        this can be computed assuming an AB source - i.e. a source with a flux
        density of 3631 jy has magnitude = 0 in the bandpass.

    Notes
    -----
        Note that this is a straight read of a single passband from a file. The
        zeropoint returned is whatever was provided (even if the value is not
        useful) or NaN. To load the passband and get the correct zeropoint, use
        :py:func:`source_synphot.passband.load_pbs`

    See Also
    --------
    :py:func:`astropy.table.Table.read`
    :py:func:`pysynphot.ObsBandpass`
    """
    if pbzp is None:
        pbzp = np.nan

    try:
        out = S.ObsBandpass(pb)
        pbzp = np.nan
    except ValueError as e:
        infile = os.path.join('passbands','pbzptmag.txt')
        pbzptfile = get_pkgfile(infile)
        pbzpt = at.Table.read(pbzptfile, format='ascii')
        ind = (pbzpt['obsmode'] == pb)
        nmatch_pb = len(pbzpt['passband'][ind])
        if nmatch_pb == 1:
            pbname = pb
            if not np.isnan(pbzpt['ABzpt'][ind][0]):
                pb = pbzpt['passband'][ind][0]
                pbzp = pbzpt['ABzpt'][ind][0]
            else:
                pbzp = np.nan
            pb = os.path.join('passbands', pb)
            try:
                pb = get_pkgfile(pb)
            except (OSError, IOError) as e:
                out = None
                pbzp = np.nan
                message = 'Passband {} not located in the passbands directory'.format(pb)
                pass
        elif nmatch_pb == 0:
            # we'll just see if this passband is a file and load it as such
            pbname = None
            message = 'Passband {} is not listed in pbzptmag file.'.format(pb)
            pass
        else:
            # pb is not unique
            out = None
            message = 'Passband {} is not uniquely listed in pbzptmag file.'.format(pb)

        if os.path.exists(pb):
            if pbname is None:
                pbname = os.path.basename(pb)
            # we either loaded the passband name from the lookup table or we didn't get a match
            pbdata = at.Table.read(pb, names=('wave','throughput'), format='ascii')
            out = S.ArrayBandpass(pbdata['wave'], pbdata['throughput'], waveunits='Angstrom', name=pbname)
        else:
            out = None
            message = 'Passband {} could not be loaded from any source.'.format(pb)

    if out is None:
        raise ValueError(message)

    try:
        pbzp = float(pbzp)
    except TypeError as e:
        message = 'Supplied zeropoint {} could not be interepreted as a float.'.format(zp)
        warnings.warn(message, RuntimeWarning)
        pbzp = np.nan
    return out, pbzp
Exemple #19
0
import pdb
from astropy.table import Table
import os
import matplotlib.pyplot as plt

pynrc.setup_logging('WARN', verbose=False)

innerGrid = np.arange(0, 1.6, 0.1)
#innerGrid = np.arange(1.5,1.6,0.1)
outerGrid = np.arange(1.6, 3.2, 0.2)

rGrid = np.hstack([innerGrid, outerGrid])

spFlat = S.FlatSpectrum(5, fluxunits='flam')

bpK = S.ObsBandpass('johnson,k')

for oneFilt, oneMask in zip(['F444W', 'F200W'], ['MASK430R', 'MASK210R']):

    satArr, sensArr = [], []
    for onePt in rGrid:
        #       print('Working on r={}'.format(onePt))
        nrc = pynrc.NIRCam(filter=oneFilt,
                           pupil='CIRCLYOT',
                           mask=oneMask,
                           wind_mode='WINDOW',
                           xpix=320,
                           ypix=320,
                           offset_r=onePt,
                           offset_theta=90,
                           read_mode='RAPID',
Exemple #20
0
 def setUp(self):
     self.sp = S.BlackBody(30000)
     self.bp = S.ObsBandpass('johnson,v')
Exemple #21
0
def get_stellar_spectrum(planet_table_entry,
                         wvs,
                         R,
                         model='Castelli-Kurucz',
                         verbose=False):
    ''' 
    A function that returns the stellar spectrum for a given spectral type

    Inputs: 
    planet_table_entry - An entry from a Universe Planet Table
    wvs - The wavelengths at which you want the spectrum. Can be an array [microns]
    R   - The spectral resolving power that you want [int or float]
    Model - The stellar spectrum moodels that you want. [string]

    Outputs:
     spectrum - returns the stellar spectrum at the desired wavelengths 
                [photons/s/cm^2/A]
    '''

    if model == 'pickles':

        #Get the pickles spectrum in units of photons/s/cm^2/angstrom.
        #Wavelength units are microns
        sp = get_pickles_spectrum(planet_table_entry['StarSpT'],
                                  verbose=verbose)

        #pysynphot  Normalizes everthing to have Vmag = 0, so we'll scale the
        #stellar spectrum by the Vmag
        starVmag = planet_table_entry['StarVmag']
        scaling_factor = 10**(starVmag / -2.5)
        full_stellar_spectrum = sp.flux * scaling_factor

        stellar_spectrum = []

        #If wvs is a float then make it a list for the for loop
        if isinstance(wvs, float):
            wvs = [wvs]

        #Now get the spectrum!
        for wv in wvs:
            #Wavelength sampling of the pickles models is at 5 angstrom
            R_in = wv / 0.0005
            #Down-sample the spectrum to the desired wavelength
            ds = downsample_spectrum(full_stellar_spectrum, R_in, R)
            #Interpolate the spectrum to the wavelength we want
            stellar_spectrum.append(si.interp1d(sp.wave, ds)(wv))
        stellar_spectrum = np.array(stellar_spectrum)

    elif model == 'Castelli-Kurucz':
        # For now we're assuming a metallicity of 0, because exosims doesn't
        # provide anything different

        #The current stellar models do not like log g > 5, so we'll force it here for now.
        star_logG = planet_table_entry['StarLogg']
        if star_logG > 5.0:
            star_logG = 5.0
        #The current stellar models do not like Teff < 3500, so we'll force it here for now.
        star_Teff = planet_table_entry['StarTeff']
        if star_Teff < 3500:
            star_Teff = 3500

        # Get the Castelli-Kurucz models
        sp = get_castelli_kurucz_spectrum(star_Teff, 0., star_logG)

        # The flux normalization in pysynphot are all over the place, but it allows
        # you to renormalize, so we will do that here. We'll normalize to the Vmag
        # of the star, assuming Johnsons filters
        sp_norm = sp.renorm(planet_table_entry['StarVmag'], 'vegamag',
                            ps.ObsBandpass('johnson,v'))

        # we normally want to put this in the get_castelli_kurucz_spectrum() function but the above line doens't work if we change units
        sp_norm.convert("Micron")
        sp_norm.convert("photlam")

        stellar_spectrum = []

        #If wvs is a float then make it a list for the for loop
        if isinstance(wvs, float):
            wvs = [wvs]

        #Now get the spectrum!
        for wv in wvs:

            #Get the wavelength sampling of the pysynphot sectrum
            dwvs = sp_norm.wave - np.roll(sp_norm.wave, 1)
            dwvs[0] = dwvs[1]
            #Pick the index closest to our wavelength.
            ind = np.argsort(np.abs((sp_norm.wave - wv)))[0]
            dwv = dwvs[ind]

            R_in = wv / dwv
            #Down-sample the spectrum to the desired wavelength
            ds = downsample_spectrum(sp_norm.flux, R_in, R)
            #Interpolate the spectrum to the wavelength we want
            stellar_spectrum.append(si.interp1d(sp_norm.wave, ds)(wv))

        stellar_spectrum = np.array(stellar_spectrum)

    else:
        if verbose:
            print("We only support 'pickles' models for now")
        return -1

    return stellar_spectrum
        os.path.join(os.getcwd(), "..", "cdbs", "grid", "phoenix",
                     "catalog.fits"))
    teff, Z, logg = np.array(()), np.array(()), np.array(())
    with pyfits.open(grid_file) as inf:
        indices = inf[1].data.field('INDEX')
        for row in indices:
            items = row.split(",")
            teff = np.append(teff, float(items[0]))
            Z = np.append(Z, float(items[1]))
            logg = np.append(logg, float(items[2]))
    return np.array(
        (np.unique(Z), np.unique(logg), np.unique(teff), np.arange(-5.5,
                                                                   16.0)))


norm_bandpass = ps.ObsBandpass('johnson,i')
coords = get_grid_points()
print(coords)
bandpasses = {}
result_arrays = {}

instruments = InstrumentList()
print("{}: Making Bandpasses...".format(time.ctime()))
for instrument in instruments:
    my_instrument = instruments[instrument]()
    bandpasses[instrument.lower()] = {}
    result_arrays[instrument.lower()] = {}
    for mode in modes[instrument.lower()]:
        for filter in filters[instrument.lower()][mode]:
            print("\t{}: {},{},{},{}".format(
                time.ctime(), instrument, mode, filter,
Exemple #23
0
    def load_passbands(self, passbands={}):
        """
        Load passbands either from pysynphot or check for an equivalent file in
        the default filter directory.
        """

        # Load default filters first
        filters = self.filters
        message = 'Loading {source} bandpasses...'
        print(message.format(source='wfc3,uvis'))
        for bp in filters['hst']['wfc3']['uvis']:
            name = 'wfc3,uvis1,'+bp
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)
        print(message.format(source='wfc3,ir'))
        for bp in filters['hst']['wfc3']['ir']:
            name = 'wfc3,ir,'+bp
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)
        print(message.format(source='acs,wfc'))
        for bp in filters['hst']['acs']['wfc']:
            name = 'acs,wfc,'+bp
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)
        print(message.format(source='acs,sbc'))
        for bp in filters['hst']['acs']['sbc']:
            name = 'acs,sbc,'+bp
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)
        print(message.format(source='swift,uvot'))
        for bp in filters['swift']['uvot']:
            file = self.options['dirs']['filters']+'/SWIFT.'+bp.upper()+'.dat'
            name = 'swift,uvot,'+bp
            wave,transmission = np.loadtxt(file, unpack=True)
            bpmodel = S.ArrayBandpass(wave, transmission,
                name=name, waveunits='Angstrom')
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)
        print(message.format(source='johnson'))
        for bp in johnson_bandpasses:
            name = 'johnson,'+bp
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)
        print(message.format(source='sdss'))
        for bp in sdss_bandpasses:
            name = 'sdss,'+bp
            bpmodel = S.ObsBandpass(name)
            self.bandpass[name] = bpmodel
            self.bandpass_names.append(name)

        # Now if there are other passbands, load them individually
        # Must be formatted as dict with {name: filename}
        for bp in passbands.keys():
            print(message.format(source=bp))
            file = passbands[bp]
            wave,transmission = np.loadtxt(file, unpack=True)
            bpmodel = S.ArrayBandpass(wave, transmission,
                name=bp, waveunits='Angstrom')
            self.bandpass[bp] = bpmodel
            self.bandpass_names.append(bp)
Exemple #24
0
ulirg_num = ["1", "2", "3", "4", "5"]
ulirg_names = ["1", "2", "3", "4", "5"]

filters = ['F125', 'F140', 'F150', 'F165']
data_dir = Path('./data/')

params = [
    'ulirg', 'x_plot', 'y_plot', 'A', 'b', 'm', 'A_err', 'b_err', 'm_err'
]

import pysynphot as S

band_names = ['f125lp', 'f140lp', 'f150lp', 'f165lp']

bands = [S.ObsBandpass('acs,sbc,%s' % band) for band in band_names]
waves = [band.wave for band in bands]

from bokeh.models.widgets import Button

s
button = Button(label="ULIRG fitting method for LYA", button_type='success')

pre = PreText(text="""details are at 

    http://homepages.spa.umn.edu/~sourabh/projects/docs/build/html/index.html?""",
              width=300,
              height=100)


def plot_lya(data_dir, filter_name, x_range, y_range):
 def make_cluster_rates(self,
                        masses,
                        instrument,
                        filter,
                        bandpass=None,
                        refs=None):
     try:
         coords = np.load(os.path.join(self.gridpath, 'input.npy'),
                          allow_pickle=True)
     except UnicodeError:
         coords = np.load(os.path.join(self.gridpath, 'input.npy'),
                          allow_pickle=True,
                          encoding='bytes')
     m, t, g, i = self.get_star_info()
     temps = np.interp(masses, m, t)
     gravs = np.interp(masses, m, g)
     mags = np.interp(masses, m, i)
     metals = np.full_like(mags, self.metallicity)
     if os.path.exists(
             os.path.join(
                 self.gridpath,
                 'result_{}_{}.npy'.format(instrument.lower(),
                                           filter.lower()))):
         values = np.load(
             os.path.join(
                 self.gridpath,
                 'result_{}_{}.npy'.format(instrument.lower(),
                                           filter.lower())))
         interpolation_function = RegularGridInterpolator(
             tuple([x for x in coords]), values)
         try:
             countrates = interpolation_function(
                 np.array((metals, gravs, temps, mags)).T)
         except ValueError as v:
             self.log('error',
                      'Exception caught when interpolating: {}'.format(v))
             min_mag = coords[-1][0]
             max_mag = coords[-1][-1]
             interpolation_function = RegularGridInterpolator(
                 tuple([x for x in coords]),
                 values,
                 bounds_error=False,
                 fill_value=0.)
             mags_min = np.full_like(mags, min_mag)
             mags_max = np.full_like(mags, max_mag)
             countrates = interpolation_function(
                 np.array((metals, gravs, temps, mags)).T)
             countrates_min = interpolation_function(
                 np.array((metals, gravs, temps, mags_min)).T)
             countrates_min = countrates_min * np.power(
                 10, -(mags - min_mag) / 2.512)
             countrates_max = interpolation_function(
                 np.array((metals, gravs, temps, mags_max)).T)
             countrates_max = countrates_max * np.power(
                 10, -(mags - max_mag) / 2.512)
             countrates[np.where(
                 mags < mags_min)] = countrates_min[np.where(
                     mags < mags_min)]
             countrates[np.where(
                 mags > mags_max)] = countrates_max[np.where(
                     mags > mags_max)]
     else:
         self.log(
             'warning',
             'Could not find result file "result_{}_{}.npy"'.format(
                 instrument.lower(), filter.lower()))
         import pysynphot as ps
         countrates = np.array(())
         ps.setref(**refs)
         johnson_i = ps.ObsBandpass('johnson,i')
         for te, log_g, z, j_i in zip(temps, gravs, metals, mags):
             spectrum = ps.Icat('phoenix', te, z, log_g)
             spectrum = spectrum.renorm(j_i, 'vegamag', johnson_i)
             obs = ps.Observation(spectrum, bandpass, binset=spectrum.wave)
             countrates = np.append(countrates, obs.countrate())
             self.log(
                 'info', 'Manually created star {} of {}'.format(
                     len(countrates), len(temps)))
     return countrates
Exemple #26
0
refimage = '../MACS1149/Catalog/MACS1149-F140W_drz_sci.fits'

#files=files[:1]

FLT = {}
for i, file in enumerate(files):
    print '%d/%d %s' % (i + 1, len(files), file)
    g = mywfc3.flt.model.GrismFLT(file=file, refimage=refimage)
    FLT[file] = g

### Full model
import pysynphot as S
xarr = np.arange(8000, 1.9e4, 40)
beta = -0.5
yarr = (xarr / 1.4e4)**beta * 10
bp = S.ObsBandpass('wfc3,ir,f140w')
spec = S.ArraySpectrum(xarr, yarr, fluxunits='flam').renorm(1, 'flam', bp)

for i, file in enumerate(files):
    #status = self.compute_model(x=281.13, y=856.8, sh=[20,20])
    print '%d/%d %s\n' % (i + 1, len(files), file)
    self = FLT[file]
    self.full_model *= 0
    skip = 40
    for xs in range(skip, 901, skip):
        for ys in range(skip, 976, skip):
            print '\x1b[1A\x1b[1M' + '%d %d' % (xs, ys)
            for beam in 'ABCD':
                status = self.compute_model(x=xs,
                                            y=ys,
                                            sh=[skip / 2, skip / 2],
 def setUp(self):
     self.sp = S.FlatSpectrum(1)
     self.bp = S.ObsBandpass('johnson,v')
Exemple #28
0
                         table['FLUX (ERG/CM2/S/A)'],
                         fluxunits='flam',
                         waveunits='Angstroms')

# Storage dict
mags = {}

if observation == 'UCAM':
    # This is the bandpass in the relevant lightpath
    telescope, instrument = "ntt", "ucam"
    # Setup the *CAM
    S.setref(**getref(telescope))

    for filt in filters:
        # Get the lightpath
        bp = S.ObsBandpass('{},{},{}'.format(telescope, instrument, filt))

        # Run the spectrum through the bandpass. Should include atmosphere?
        obs = S.Observation(sp, bp, force="taper")

        # Convert to magnitude
        ADU_flux = obs.countrate()
        mag = obs.effstim('abmag')

        mags[filt] = mag

        print("Band: {}".format(filt))
        print("Countrate: {:.3f}".format(ADU_flux))
        print("abmag: {:.3f}\n".format(mag))

elif observation == 'SDSS':
Exemple #29
0
# ---
# jupyter:
#   jupytext_format_version: '1.2'
#   kernelspec:
#     display_name: Python [conda env:astroconda]
#     language: python
#     name: conda-env-astroconda-py
#   language_info:
#     codemirror_mode:
#       name: ipython
#       version: 3
#     file_extension: .py
#     mimetype: text/x-python
#     name: python
#     nbconvert_exporter: python
#     pygments_lexer: ipython3
#     version: 3.5.1
# ---

import numpy as np
import pysynphot as S

bp1 = S.ObsBandpass('acs,wfc1,f555w')

bp1.unit_response()

bp1.obsmode.modes

S.ObsBandpass?
def etc_uh_roboAO(mag, filt_name, tint, sq_aper_diam=0.3, phot_sys='Vega', spec_res=100, 
                  seeing_limited=False):
    """
    Exposure time calculator for a UH Robo-AO system and a NIR IFU spectrograph.

    phot_sys - 'Vega' (default) or 'AB'
    """
    
    ifu_throughput = 0.35
    #ao_throughput = 0.55
    ao_throughput = 0.76  # New Design
    tel_throughput = 0.85**2

    if seeing_limited:
        sys_throughput = ifu_throughput * tel_throughput
    else:
        sys_throughput = ifu_throughput * ao_throughput * tel_throughput
    
    # TO DO Need to add telescope secondary obscuration to correct the area.
    tel_area = math.pi * (2.22 * 100. / 2.)**2   # cm^2 for UH 2.2m tel
    sec_area = math.pi * (0.613 * 100. / 2.)**2   # cm^2 for UH 2.2m tel hole/secondary obscuration
    tel_area -= sec_area
    
    read_noise = 3.0       # electrons
    dark_current = 0.01    # electrons s^-1

    # Get the filter
    if filt_name == 'Z' or filt_name == 'Y':
        filt = get_ukirt_filter(filt_name)
    else:
        filt = pysynphot.ObsBandpass(filt_name)

    # Calculate the wave set for the IFU. Include Nyquist sampled pixels.
    dlamda = (filt.avgwave() / spec_res) / 2.0
    ifu_wave = np.arange(filt.wave.min(), filt.wave.max()+dlamda, dlamda)

    # Estimate the number of pixels across our spectrum.
    npix_spec = len(ifu_wave)
    
    # Get the Earth transmission spectrum. Sample everything
    # onto this grid.
    earth_trans =  read_mk_sky_transmission()

    # Get the Earth background emission spectrum
    earth_bkg = read_mk_sky_emission_ir()
    earth_bkg.resample(ifu_wave)

    # Convert to Vega if in AB
    if phot_sys != 'Vega':
        mag += Vega_to_AB[filt_name]

    # Assume this star is an A0V star, so just scale a Vega spectrum
    # to the appropriate magnitude. Rescale to match the magnitude.
    # pysynphot.renorm() and pysynphot.setMagnitude are all broken.
    star = pysynphot.Vega.renorm(mag, 'vegamag', filt)  # erg cm^2 s^-1 A^-1

    # Observe the star and background through a filter and resample
    # at the IFU spectral sampling.
    star_obs = observation.Observation(star, filt, binset=ifu_wave)
    bkg_obs = observation.Observation(earth_bkg, filt, binset=ifu_wave, force="extrap")
    vega = pysynphot.FileSpectrum(pysynphot.locations.VegaFile)
    vega_obs = observation.Observation(vega, filt, binset=ifu_wave)

    # Propogate the star flux and background through the
    # atmosphere and telescope. 
    star_obs *= earth_trans                       # erg s^-1 A^-1 cm^-2
    star_obs *= tel_area * sys_throughput         # erg s^-1 A^-1
    vega_obs *= earth_trans                       # erg s^-1 A^-1 cm^-2
    vega_obs *= tel_area * sys_throughput         # erg s^-1 A^-1
    bkg_obs *= tel_area * sys_throughput          # erg s^-1 A^-1 arcsec^-2

    # Convert them into photlam
    star_obs.convert('photlam')            # photon s^-1 A^-1
    vega_obs.convert('photlam')
    bkg_obs.convert('photlam')             # photon s^-1 A^-1 arcsec^-2

    # Pull the arrays out of the Observation objects
    star_counts = star_obs.binflux
    bkg_counts = bkg_obs.binflux
    vega_counts = vega_obs.binflux
    
    # Integrate each spectral channel using the ifu_wave (dlamda defined above).
    star_counts *= dlamda                     # photon s^-1
    bkg_counts *= dlamda                      # photon s^-1 arcsec^-2
    vega_counts *= dlamda                     # photon s^-1 NO? arcsec^-2

    # Integrate over the aperture for the background and make
    # an aperture correction for the star.
    if seeing_limited:
        ee = get_seeing_ee(filt_name, sq_aper_diam)
    else:
        ee = get_roboAO_ee(mag, filt_name, sq_aper_diam)
        
    aper_area = sq_aper_diam**2               # square
    star_counts *= ee                         # photon s^-1
    # TODO... Don't I need to do this for vega as well?
    # vega_counts *= ee  
    bkg_counts *= aper_area                   # photon s^-1 arcsec^-2

    pix_scale = 0.150                      # arcsec per pixel
    if seeing_limited:
        pix_scale = 0.400
        
    npix = (aper_area / pix_scale**2)
    npix *= npix_spec

    vega_mag = 0.03
    star_mag = -2.5 * math.log10(star_counts.sum() / vega_counts.sum()) + vega_mag
    bkg_mag = -2.5 * math.log10(bkg_counts.sum() / vega_counts.sum()) + vega_mag
    
    signal = star_counts * tint               # photon
    bkg = bkg_counts * tint                   # photon
    
    noise_variance = signal.copy()
    noise_variance += bkg
    noise_variance += read_noise**2 * npix
    noise_variance += dark_current * tint * npix
    noise = noise_variance**0.5
    snr_spec = signal / noise
    
    # Calculate average signal-to-noise per spectral channel        
    avg_signal = signal.sum()
    avg_noise = noise.sum()
    avg_snr = avg_signal / avg_noise

    msg = 'filt = {0:s}  signal = {1:13.1f}  bkg = {2:9.1f}  SNR = {3:7.1f}'
    print msg.format(filt_name, avg_signal, bkg.mean(), avg_snr)

    # Inter-OH gives an overal reduction in background of
    # 2.3 mag at H - probably slightly less than this because this was with NIRSPEC
    # 2.0 mag at J

    # Do R=100
    # Do R=30
    
    return avg_snr, star_mag, bkg_mag, ifu_wave, signal, bkg, snr_spec