예제 #1
0
 def setUp(self):
     self.bb = S.BlackBody(5000)
     self.em = S.GaussianSource(3300, 1, 1)
     self.flat = S.FlatSpectrum(10)
     self.pl = S.PowerLaw(5000, -2)
     self.tspec = S.ArraySpectrum(self.bb.wave,
                                  self.bb.flux,
                                  fluxunits=self.bb.fluxunits)
     self.pl.writefits('ac_pl.fits')
     self.fspec = S.FileSpectrum('ac_pl.fits')
예제 #2
0
    def test_conversion1(self):
        pl = S.PowerLaw(6000, -4, 'angstrom', 'photlam')

        angflux = pl.sample(self.wave)

        pl.convert('nm')

        nmflux = pl.sample(self.wave / 10.)

        self.assertEqualNumpy(nmflux, angflux)
예제 #3
0
    def test_conversion2(self):
        pl = S.PowerLaw(6000, -4, 'angstrom', 'photlam')

        self.assertEqualNumpy(
            pl.sample(self.wave)[:10], pl.sample(self.wave[:10]))

        pl.convert('nm')

        self.assertEqualNumpy(
            pl.sample(self.wave)[:10], pl.sample(self.wave[:10]))
예제 #4
0
    def test_values(self):
        ref = np.array([
            16., 15.78843266, 15.58035072, 15.37568551, 15.17436992,
            14.97633838, 14.78152682, 14.5898726, 14.40131453, 14.21579277
        ])

        pl = S.PowerLaw(6000, -4, 'angstrom', 'photlam')

        test = pl.sample(self.wave[:10])

        self.assertApproxNumpy(test, ref)
예제 #5
0
 def __init__(self, refwave, beta, redshift, A=1.0, verbose=False):
     self.rspec = S.PowerLaw(refwave,
                             beta,
                             waveunits='angstrom',
                             fluxunits='flam')
     # self.factory = FileSED.GalaxySEDFactory(spec=rspec)
     # Redshift the spectrum & add IGM attenuation
     # self.rspec = self.factory.redshift(redshift)  # the reference spectrum
     mag = S.Observation(self.rspec, filters['f160w']).effstim('abmag')
     # normalize reference spectrum to 25.0 mag in F160W to minimize
     # round-off errors later in fitting
     dmag = 25.0 - mag
     self.rspec = 10.**(-0.4 * dmag) * self.rspec
     A = np.abs(A)
     self.rspec = A * self.rspec
     self.beta = beta
     self.A = A
     self.verbose = verbose
예제 #6
0
def read_source(sourcespec):
    """
    Read a spectrum

    Parameters
    ----------
    sourcespec : str
        Source spectrum specification string. Acceptable options are:
         * BB<Temperature>
         * PL<Reference Wave Angstrom>_<PL Index>
         * Flat<AB magnitude>
         * ckmod<Temperature>_<logZ>_<logg>

    Returns
    -------
    source : :py:class:`pysynphot.spectrum.ArraySourceSpectrum`
        The spectrum data.
        Has ``dtype=[('wave', '<f8'), ('flux', '<f8')]``

    Raises
    ------
    ValueError
        If attempting to use this routine to load a file, or if source spectrum
        specification string is invalid

    Notes
    -----
       The source spectrum specification string parsing is basic. Strings are
       checked to see if they start with an acceptable prefix, and then split.
       The individual constituents are converted to float, and passed to
       pysynphot. There is no checking of the values, only that they can be
       properly typecast into float. Making sure the value is accepted is left
       to the user.

    """
    if os.path.exists(sourcespec):
        message = 'File spectrum parsing is complex and requires pre-processing. Use source_synphot.source routines'
        raise ValueError(message)
    else:
        # assume sourcespec is a string and parse it, trying to interpret as:
        # simple blackbody spectrum
        if sourcespec.startswith('BB'):
            temp = sourcespec.lstrip('BB')
            try:
                temp = float(temp)
            except (TypeError, ValueError) as e:
                message = 'Source temperature {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            bb = S.Blackbody(temp)
            bb.convert('flam')
            spec = {'wave':bb.wave, 'flux':bb.flux}

        # power-law spectrum
        elif sourcespec.startswith('PL'):
            refwave, plindex = sourcespec.lstrip('PL').split('_')
            try:
                refwave = float(refwave)
            except (TypeError, ValueError) as e:
                message = 'Reference wavelength {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            try:
                plindex = float(plindex)
            except (TypeError, ValueError) as e:
                message = 'Power law index {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            pl = S.PowerLaw(refwave, plindex)
            pl.convert('flam')
            spec = {'wave':pl.wave, 'flux':pl.flux}

        # flat spectrum (in f_lam, not f_nu) normalized to some ABmag
        elif sourcespec.startswith('Flat'):
            abmag = sourcespec.replace('Flat','')
            try:
                abmag = float(abmag)
            except (TypeError, ValueError) as e:
                message = 'AB mag {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            flat = S.FlatSpectrum(abmag, fluxunits='abmag')
            flat.convert('flam')
            spec = {'wave':flat.wave, 'flux':flat.flux}

        # a Castelli-Kurucz model
        elif sourcespec.startswith('ckmod'):
            teff, logZ, logg = sourcespec.replace('ckmod','').split('_')
            try:
                teff = float(teff)
            except (TypeError, ValueError) as e:
                message = 'Source temperature {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            try:
                logZ = float(logZ)
            except (TypeError, ValueError) as e:
                message = 'Abundance {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            try:
                logg = float(logg)
            except (TypeError, ValueError) as e:
                message = 'Surface gravity {} cannot be interpreted as a float'.format(sourcespec)
                raise ValueError(message)
            ckmod = S.Icat('ck04models',teff, logZ,logg)
            ckmod.convert('flam')
            spec = {'wave':ckmod.wave, 'flux':ckmod.flux}

        # else give up
        else:
            message = 'Source spectrum {} cannot be parsed as input file or pre-defined type (BB, PL, Flat, ckmod)'.format(sourcespec)
            raise ValueError(message)
    spec = S.ArraySpectrum(spec['wave'], spec['flux'], name=sourcespec)
    return spec
예제 #7
0
def specFromSpectralType(sptype, return_list=False, catalog=None):
    """Get Pysynphot Spectrum object from a user-friendly spectral type string.

    Given a spectral type such as 'A0IV' or 'G2V', this uses a fixed lookup table
    to determine an appropriate spectral model from Castelli & Kurucz 2004 or 
    the Phoenix model grids. Depends on pysynphot and CDBS. This is just a
    convenient access function.

    Parameters
    -----------
    catalog: str
        'ck04' for Castelli & Kurucz 2004, 'phoenix' for Phoenix models.
        If not set explicitly, the code will check if the phoenix models are
        present inside the $PYSYN_CDBS directory. If so, those are the default;
        otherwise, it's CK04.

    """
    import pysynphot


    if catalog is None: 
        import os
        cdbs = os.getenv('PYSYN_CDBS')
        if os.path.exists( os.path.join(os.getenv('PYSYN_CDBS'), 'grid', 'phoenix')):
            catalog='phoenix'
        elif os.path.exists( os.path.join(os.getenv('PYSYN_CDBS'), 'grid', 'ck04models')):
            catalog='ck04'
        else:
            raise IOError("Could not find either phoenix or ck04models subdirectories of $PYSYN_CDBS/grid")

    if catalog.lower()  =='ck04':
        catname='ck04models'

        # Recommended lookup table into the CK04 models (from 
        # the documentation of that catalog?)
        lookuptable = {
            "O3V":   (50000, 0.0, 5.0),
            "O5V":   (45000, 0.0, 5.0),
            "O6V":   (40000, 0.0, 4.5),
            "O8V":   (35000, 0.0, 4.0),
            "O5I":   (40000, 0.0, 4.5),
            "O6I":   (40000, 0.0, 4.5),
            "O8I":   (34000, 0.0, 4.0),
            "B0V":   (30000, 0.0, 4.0),
            "B3V":   (19000, 0.0, 4.0),
            "B5V":   (15000, 0.0, 4.0),
            "B8V":   (12000, 0.0, 4.0),
            "B0III": (29000, 0.0, 3.5),
            "B5III": (15000, 0.0, 3.5),
            "B0I":   (26000, 0.0, 3.0),
            "B5I":   (14000, 0.0, 2.5),
            "A0V":   (9500, 0.0, 4.0),
            "A5V":   (8250, 0.0, 4.5),
            "A0I":   (9750, 0.0, 2.0),
            "A5I":   (8500, 0.0, 2.0),
            "F0V":   (7250, 0.0, 4.5),
            "F5V":   (6500, 0.0, 4.5),
            "F0I":   (7750, 0.0, 2.0),
            "F5I":   (7000, 0.0, 1.5),
            "G0V":   (6000, 0.0, 4.5),
            "G5V":   (5750, 0.0, 4.5),
            "G0III": (5750, 0.0, 3.0),
            "G5III": (5250, 0.0, 2.5),
            "G0I":   (5500, 0.0, 1.5),
            "G5I":   (4750, 0.0, 1.0),
            "K0V":   (5250, 0.0, 4.5),
            "K5V":   (4250, 0.0, 4.5),
            "K0III": (4750, 0.0, 2.0),
            "K5III": (4000, 0.0, 1.5),
            "K0I":   (4500, 0.0, 1.0),
            "K5I":   (3750, 0.0, 0.5),
            "M0V":   (3750, 0.0, 4.5),
            "M2V":   (3500, 0.0, 4.5),
            "M5V":   (3500, 0.0, 5.0),
            "M0III": (3750, 0.0, 1.5),
            "M0I":   (3750, 0.0, 0.0),
            "M2I":   (3500, 0.0, 0.0)}
    elif catalog.lower() =='phoenix':
        catname='phoenix'
        # lookup table used in JWST ETCs
        lookuptable = {
            "O3V":   (45000, 0.0, 4.0),
            "O5V":   (41000, 0.0, 4.5),
            "O7V":   (37000, 0.0, 4.0),
            "O9V":   (33000, 0.0, 4.0),
            "B0V":   (30000, 0.0, 4.0),
            "B1V":   (25000, 0.0, 4.0),
            "B3V":   (19000, 0.0, 4.0),
            "B5V":   (15000, 0.0, 4.0),
            "B8V":   (12000, 0.0, 4.0),
            "A0V":   (9500, 0.0, 4.0),
            "A1V":   (9250, 0.0, 4.0),
            "A3V":   (8250, 0.0, 4.0),
            "A5V":   (8250, 0.0, 4.0),
            "F0V":   (7250, 0.0, 4.0),
            "F2V":   (7000, 0.0, 4.0),
            "F5V":   (6500, 0.0, 4.0),
            "F8V":   (6250, 0.0, 4.5),
            "G0V":   (6000, 0.0, 4.5),
            "G2V":   (5750, 0.0, 4.5),
            "G5V":   (5750, 0.0, 4.5),
            "G8V":   (5500, 0.0, 4.5),
            "K0V":   (5250, 0.0, 4.5),
            "K2V":   (4750, 0.0, 4.5),
            "K5V":   (4250, 0.0, 4.5),
            "K7V":   (4000, 0.0, 4.5),
            "M0V":   (3750, 0.0, 4.5),
            "M2V":   (3500, 0.0, 4.5),
            "M5V":   (3500, 0.0, 5.0),
            "B0III": (29000, 0.0, 3.5),
            "B5III": (15000, 0.0, 3.5),
            "G0III": (5750, 0.0, 3.0),
            "G5III": (5250, 0.0, 2.5),
            "K0III": (4750, 0.0, 2.0),
            "K5III": (4000, 0.0, 1.5),
            "M0III": (3750, 0.0, 1.5),
            "O6I":   (39000, 0.0, 4.5),
            "O8I":   (34000, 0.0, 4.0),
            "B0I":   (26000, 0.0, 3.0),
            "B5I":   (14000, 0.0, 2.5),
            "A0I":   (9750, 0.0, 2.0),
            "A5I":   (8500, 0.0, 2.0),
            "F0I":   (7750, 0.0, 2.0),
            "F5I":   (7000, 0.0, 1.5),
            "G0I":   (5500, 0.0, 1.5),
            "G5I":   (4750, 0.0, 1.0),
            "K0I":   (4500, 0.0, 1.0),
            "K5I":   (3750, 0.0, 0.5),
            "M0I":   (3750, 0.0, 0.0),
            "M2I":   (3500, 0.0, 0.0)}

    if return_list:
        sptype_list = lookuptable.keys()
        def sort_sptype(typestr):
            letter = typestr[0]
            lettervals = {'O':0, 'B': 10, 'A': 20,'F': 30, 'G':40, 'K': 50, 'M':60}
            value = lettervals[letter]*1.0
            value += int(typestr[1])
            if "III" in typestr: value += .3
            elif "I" in typestr: value += .1
            elif "V" in typestr: value += .5
            return value
        sptype_list.sort(key=sort_sptype)
        sptype_list.insert(0,"Flat spectrum in F_nu")
        sptype_list.insert(0,"Flat spectrum in F_lambda")
        # add a variety of spectral type slopes, per request from Dean Hines
        for slope in [-3, -2, -1.5, -1, -0.75, -0.5, 0.5, 0.75, 1.0, 1.5, 2, 3]:
            sptype_list.insert(0,"Power law F_nu ~ nu^(%s)" % str(slope))
        #sptype_list.insert(0,"Power law F_nu ~ nu^(-0.75)")
        #sptype_list.insert(0,"Power law F_nu ~ nu^(-1.0)")
        #sptype_list.insert(0,"Power law F_nu ~ nu^(-1.5)")
        #sptype_list.insert(0,"Power law F_nu ~ nu^(-2.0)")
        return sptype_list


    if "Flat" in sptype:
        if sptype == "Flat spectrum in F_nu":    spec = pysynphot.FlatSpectrum( 1, fluxunits = 'fnu')
        elif sptype == "Flat spectrum in F_lambda":  spec= pysynphot.FlatSpectrum( 1, fluxunits = 'flam')
        spec.convert('flam')
        return spec*(1./spec.flux.mean())
    if 'Power law' in sptype:
        import re
        ans = re.search('\((.*)\)', sptype)
        if ans is None: raise ValueError("Invalid power law specification cannot be parsed to get exponent")
        exponent = float(ans.groups(0)[0])
        # note that Pysynphot's PowerLaw class implements a power law in terms of lambda, not nu.
        # but since nu = clight/lambda, it's just a matter of swapping the sign on the exponent. 

        spec = pysynphot.PowerLaw(1, (-1)*exponent, fluxunits='fnu')
        spec.convert('flam')
        spec *= (1./spec.flux.mean())
        spec.name = sptype
        return spec
    else: 
        keys = lookuptable[sptype]
        try:
            return pysynphot.Icat(catname,keys[0], keys[1], keys[2])
        except:
            errmsg = "Could not find a match in catalog {0} for key {1}. Check that is a valid name in the lookup table, and/or that pysynphot is installed properly.".format(catname, sptype)
            _log.critical(errmsg)
            raise LookupError(errmsg)
예제 #8
0
 def setUp(self):
     self.sp=S.PowerLaw(10000,0.5)