def test_rn_bb_box_abmag(): sp1 = spparser.parse_spec('rn(bb(5000), box(5000, 10), 17, abmag)') _single_functioncall(sp1, SourceSpectrum, None, 'rn(bb(5000.0),box(5000.0,10.0),17.0,abmag)') bb = SourceSpectrum(BlackBodyNorm1D, temperature=5000 * u.K) box = SpectralElement(Box1D, amplitude=1, x_0=5000 * u.AA, width=10 * u.AA) sp2 = bb.normalize(17 * u.ABmag, band=box) _compare_spectra(sp1, sp2)
def test_remote_rn_powerlaw(): sp1 = spparser.parse_spec('rn(pl(5000, 1, flam), band(v), 1, photlam)') _single_functioncall(sp1, SourceSpectrum, None, 'rn(pl(5000.0,1.0,flam),band(v),1.0,photlam)') pl = SourceSpectrum(PowerLawFlux1D, amplitude=1 * units.FLAM, x_0=5000 * u.AA, alpha=-1) bp = SpectralElement.from_filter('johnson_v') sp2 = pl.normalize(1 * units.PHOTLAM, band=bp) _compare_spectra(sp1, sp2)
def test_z_em(): sp1 = spparser.parse_spec('z(em(5000, 25, 1, flam), 0.1)') _single_functioncall( sp1, SourceSpectrum, None, 'z(em(5000, 25, 1, FLAM),0.1)', ans_z=0.1) f = 1 * (units.FLAM * u.AA) # Integrated flux sp2 = SourceSpectrum( GaussianFlux1D, mean=5000 * u.AA, fwhm=25 * u.AA, total_flux=f) sp2.z = 0.1 _compare_spectra(sp1, sp2)
def test_remote_rn_unit_1_flam(): sp1 = spparser.parse_spec( 'rn(unit(1,flam), band(acs, wfc1, fr388n#3881.0), 10, abmag)') _single_functioncall( sp1, SourceSpectrum, None, 'rn(unit(1.0,flam),band(acs,wfc1,fr388n#3881.0),10.0,abmag)') constsp = SourceSpectrum(ConstFlux1D, amplitude=1 * units.FLAM) bp = spectrum.band('acs, wfc1, fr388n#3881.0') sp2 = constsp.normalize(10 * u.ABmag, band=bp) _compare_spectra(sp1, sp2)
def load_vega(vegafile=None, **kwargs): """Convenience function to load Vega spectrum that is used throughout `stsynphot`. Parameters ---------- vegafile : str or `None`, optional Vega spectrum filename. If `None`, use ``synphot.config.conf.vega_file``. kwargs : dict Keywords acceptable by :func:`synphot.specio.read_remote_spec`. Returns ------- sp : `synphot.spectrum.SourceSpectrum` or `None` Vega spectrum. `None` if failed. """ global Vega if vegafile is None: vegafile = synconf.vega_file with synconf.set_temp('vega_file', vegafile): try: Vega = SourceSpectrum.from_vega(**kwargs) except Exception as e: Vega = None warnings.warn( 'Failed to load Vega spectrum from {0}; Functionality ' 'involving Vega will be cripped: {1}'.format( vegafile, str(e)), AstropyUserWarning)
def test_z_null(): """ETC junk spectrum results in flat spectrum with no redshift.""" sp1 = spparser.parse_spec('z(null, 0.1)') _single_functioncall(sp1, SourceSpectrum, ConstFlux1D, 'z(null,0.1)') sp2 = SourceSpectrum(ConstFlux1D, amplitude=1 * units.PHOTLAM) _compare_spectra(sp1, sp2)
def test_remote_spec_vegafile(): sp1 = spparser.parse_spec('spec(crcalspec$alpha_lyr_stis_007.fits)') _single_functioncall(sp1, SourceSpectrum, Empirical1D, 'spec(crcalspec$alpha_lyr_stis_007.fits)') sp2 = SourceSpectrum.from_file(resolve_filename( os.environ['PYSYN_CDBS'], 'calspec', 'alpha_lyr_stis_007.fits')) _compare_spectra(sp1, sp2)
def test_powerlaw_5000_1_flam(): sp1 = spparser.parse_spec('pl(5000, 1, flam)') _single_functioncall( sp1, SourceSpectrum, PowerLawFlux1D, 'pl(5000.0,1.0,flam)') sp2 = SourceSpectrum(PowerLawFlux1D, amplitude=1 * units.FLAM, x_0=5000 * u.AA, alpha=-1) _compare_spectra(sp1, sp2)
def test_em_5000_25_1_flam(): sp1 = spparser.parse_spec('em(5000, 25, 1, flam)') _single_functioncall( sp1, SourceSpectrum, GaussianFlux1D, 'em(5000, 25, 1, FLAM)') f = 1 * (units.FLAM * u.AA) # Integrated flux sp2 = SourceSpectrum( GaussianFlux1D, mean=5000 * u.AA, fwhm=25 * u.AA, total_flux=f) _compare_spectra(sp1, sp2)
def test_remote_z_vega(): sp1 = spparser.parse_spec('z(crcalspec$alpha_lyr_stis_007.fits, 0.1)') _single_functioncall(sp1, SourceSpectrum, None, 'z(crcalspec$alpha_lyr_stis_007.fits,0.1)', ans_z=0.1) sp2 = SourceSpectrum.from_file(resolve_filename( os.environ['PYSYN_CDBS'], 'calspec', 'alpha_lyr_stis_007.fits')) sp2.z = 0.1 _compare_spectra(sp1, sp2)
def to_spectrum(self): """Get thermal spectrum. The calculations start with zero-flux spectrum. Then for each component: #. Multiply with optical throughput. #. Add in thermal source spectrum from :meth:`synphot.thermal.ThermalSpectralElement.thermal_source`. Returns ------- sp : `synphot.spectrum.SourceSpectrum` Thermal spectrum in PHOTLAM. """ # Create zero-flux spectrum x = self._get_wave_intersection() # Angstrom y = np.zeros_like(x, dtype=np.float64) # PHOTLAM minw, maxw = x[([0, -1], )] sp = SourceSpectrum(Empirical1D, points=x, lookup_table=y) for component in self.components: # Transmissive section (optical passband) if component.throughput is not None: sp = sp * component.throughput # Thermal section if component.emissivity is not None: sp = sp + component.emissivity.thermal_source() # Trim spectrum w = sp.waveset.value mask = (w >= minw) & (w <= maxw) x = w[mask] y = sp(x) sp = SourceSpectrum(Empirical1D, points=x, lookup_table=y) meta = {'expr': f'{self._obsmode} ThermalSpectrum'} sp.meta.update(meta) return sp
def test_remote_rn_calspec_box(): sp1 = spparser.parse_spec( 'rn(crcalspec$gd71_mod_005.fits, box(5000, 10), 17, vegamag)') _single_functioncall( sp1, SourceSpectrum, None, 'rn(crcalspec$gd71_mod_005.fits,box(5000.0,10.0),17.0,vegamag)') gd71 = SourceSpectrum.from_file(resolve_filename( os.environ['PYSYN_CDBS'], 'calspec', 'gd71_mod_005.fits')) box = SpectralElement(Box1D, amplitude=1, x_0=5000 * u.AA, width=10 * u.AA) sp2 = gd71.normalize(17 * units.VEGAMAG, band=box, vegaspec=spectrum.Vega) _compare_spectra(sp1, sp2)
def _get_spectrum(parlist, catdir): """Get list of spectra for given parameter list and base name.""" name = parlist[3] filename = name.split('[')[0] column = name.split('[')[1][:-1] filename = os.path.join(catdir, filename) sp = SourceSpectrum.from_file(filename, flux_col=column) result = [member for member in parlist] result.pop() result.append(sp) return result
def test_remote_rn_calspec_u(): sp1 = spparser.parse_spec( 'rn(crcalspec$bd_75d325_stis_002.fits, band(u), 9.5, vegamag) * ' 'band(fos, blue, 4.3, g160l)') # NOTE: No expr for this combo. _single_functioncall(sp1, SourceSpectrum, None, '') bd75 = SourceSpectrum.from_file(resolve_filename( os.environ['PYSYN_CDBS'], 'calspec', 'bd_75d325_stis_002.fits')) bp_u = SpectralElement.from_filter('johnson_u') bd75_norm = bd75.normalize( 9.5 * units.VEGAMAG, band=bp_u, vegaspec=spectrum.Vega) bp_fos = spectrum.band('fos, blue, 4.3, g160l') sp2 = bd75_norm * bp_fos _compare_spectra(sp1, sp2)
def _convertstr(value): """Convert given filename to source spectrum or passband. This is used by the interpreter to do the conversion from string to spectrum object. """ if not isinstance(value, str): return value value = irafconvert(value) try: sp = SourceSpectrum.from_file(value) except KeyError: sp = SpectralElement.from_file(value) return sp
def _get_spectrum(parlist, catdir): """Get list of spectra for given parameter list and base name.""" name = parlist[3] filename = name.split('[')[0] column = name.split('[')[1][:-1] filename = os.path.join(catdir, filename) sp = SourceSpectrum.from_file(filename, flux_col=column) totflux = sp.integrate() try: validate_totalflux(totflux) except synexceptions.SynphotError: raise exceptions.ParameterOutOfBounds( "Parameter '{0}' has no valid data.".format(parlist)) result = [member for member in parlist] result.pop() result.append(sp) return result
def test_bb_5000(): sp1 = spparser.parse_spec('bb(5000)') _single_functioncall(sp1, SourceSpectrum, BlackBodyNorm1D, 'bb(5000.0)') sp2 = SourceSpectrum(BlackBodyNorm1D, temperature=5000 * u.K) _compare_spectra(sp1, sp2)
def test_unit_1_flam(): sp1 = spparser.parse_spec('unit(1, flam)') _single_functioncall(sp1, SourceSpectrum, ConstFlux1D, 'unit(1.0,flam)') sp2 = SourceSpectrum(ConstFlux1D, amplitude=1 * units.FLAM) _compare_spectra(sp1, sp2)
def p_functioncall(self, tree): # Where all the real interpreter action is. # Note that things that should only be done at the top level # are performed in :func:`interpret` defined below. """ V ::= function_call ( V LPAREN V RPAREN ) """ if not isinstance(tree[2].value, list): args = [tree[2].value] else: args = tree[2].value fname = tree[0].value metadata = {'expr': '{0}{1}'.format(fname, tuple(args))} if fname not in _SYFUNCTIONS: log.error('Unknown function: {0}'.format(fname)) self.error(fname) else: # Constant spectrum if fname == 'unit': if args[1] not in _SYFORMS: log.error('Unrecognized unit: {0}'.format(args[1])) self.error(fname) try: fluxunit = units.validate_unit(args[1]) tree.value = SourceSpectrum(ConstFlux1D, amplitude=args[0] * fluxunit, meta=metadata) except NotImplementedError as e: log.error(str(e)) self.error(fname) # Black body elif fname == 'bb': tree.value = SourceSpectrum(BlackBodyNorm1D, temperature=args[0]) # Power law elif fname == 'pl': if args[2] not in _SYFORMS: log.error('Unrecognized unit: {0}'.format(args[2])) self.error(fname) try: fluxunit = units.validate_unit(args[2]) tree.value = SourceSpectrum(PowerLawFlux1D, amplitude=1 * fluxunit, x_0=args[0], alpha=-args[1], meta=metadata) except (synexceptions.SynphotError, NotImplementedError) as e: log.error(str(e)) self.error(fname) # Box throughput elif fname == 'box': tree.value = SpectralElement(Box1D, amplitude=1, x_0=args[0], width=args[1], meta=metadata) # Source spectrum from file elif fname == 'spec': tree.value = SourceSpectrum.from_file(irafconvert(args[0])) tree.value.meta.update(metadata) # Passband elif fname == 'band': tree.value = spectrum.band(tree[2].svalue) tree.value.meta.update(metadata) # Gaussian emission line elif fname == 'em': if args[3] not in _SYFORMS: log.error('Unrecognized unit: {0}'.format(args[3])) self.error(fname) x0 = args[0] fluxunit = units.validate_unit(args[3]) totflux = units.convert_flux(x0, args[2] * fluxunit, units.PHOTLAM).value tree.value = SourceSpectrum(GaussianFlux1D, total_flux=totflux, mean=x0, fwhm=args[1]) # Catalog interpolation elif fname == 'icat': tree.value = grid_to_spec(*args) # Renormalize source spectrum elif fname == 'rn': sp = args[0] bp = args[1] fluxunit = units.validate_unit(args[3]) rnval = args[2] * fluxunit if not isinstance(sp, SourceSpectrum): sp = SourceSpectrum.from_file(irafconvert(sp)) if not isinstance(bp, SpectralElement): bp = SpectralElement.from_file(irafconvert(bp)) # Always force the renormalization to occur: prevent exceptions # in case of partial overlap. Less robust but duplicates # IRAF SYNPHOT. Force the renormalization in the case of # partial overlap, but raise an exception if the spectrum and # bandpass are entirely disjoint. try: tree.value = sp.normalize(rnval, band=bp, area=conf.area, vegaspec=spectrum.Vega) except synexceptions.PartialOverlap: tree.value = sp.normalize(rnval, band=bp, area=conf.area, vegaspec=spectrum.Vega, force=True) tree.value.warnings = { 'force_renorm': ('Renormalization exceeds the limit ' 'of the specified passband.') } tree.value.meta.update(metadata) # Redshift source spectrum (flat spectrum if fails) elif fname == 'z': sp = args[0] # ETC generates junk (i.e., 'null') sometimes if isinstance(sp, str) and sp != 'null': sp = SourceSpectrum.from_file(irafconvert(sp)) if isinstance(sp, SourceSpectrum): tree.value = sp tree.value.z = args[1] else: tree.value = SourceSpectrum(ConstFlux1D, amplitude=1) tree.value.meta.update(metadata) # Extinction elif fname == 'ebmvx': try: tree.value = spectrum.ebmvx(args[1], args[0]) except synexceptions.SynphotError as e: log.error(str(e)) self.error(fname) tree.value.meta.update(metadata) # Default else: tree.value = ('would call {0} with the following args: ' '{1}'.format(fname, repr(args)))
def setup_class(self): self.outdir = tempfile.mkdtemp() self.obs = spectrum.band('acs,hrc,f555w', graphtable=GT_FILE, comptable=CP_FILE) self.sp = SourceSpectrum(ConstFlux1D, amplitude=1 * units.FLAM)