def test_conversion3(self): g = S.GaussianSource(1, 4000, 100, 'angstrom', 'photlam') tf1 = g.total_flux g.convert('nm') tf2 = g.factor * g.sigma * np.sqrt(2.0 * np.pi) self.assertEqual(tf1, tf2)
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')
def test_conversion1(self): g = S.GaussianSource(1, 4000, 100, 'angstrom', 'photlam') angflux = g.sample(self.wave) g.convert('nm') nmflux = g.sample(self.wave / 10.) self.assertEqualNumpy(nmflux, angflux)
def test_conversion2(self): g = S.GaussianSource(1, 4000, 100, 'angstrom', 'photlam') self.assertEqualNumpy( g.sample(self.wave)[:10], g.sample(self.wave[:10])) g.convert('nm') self.assertEqualNumpy( g.sample(self.wave)[:10], g.sample(self.wave[:10]))
def test_values(self): ref = np.array([ 3.63805721e-123, 9.05875032e-121, 2.13395205e-118, 4.75574568e-116, 1.00269809e-113, 2.00004310e-111, 3.77421053e-109, 6.73799198e-107, 1.13802672e-104, 1.81841090e-102 ]) g = S.GaussianSource(1, 4000, 100, 'angstrom', 'photlam') test = g.sample(self.wave[:10]) self.assertApproxNumpy(test, ref)
def rudy_ic5117(): """ Make a simple spectrum from the line table from Rudy et al. """ from astropy.table import Table as table import pysynphot as S t = table.read('rudy_table1.dat.txt', format='ascii.cds') spec = S.FlatSpectrum(6e-11*1.e-4, fluxunits='photlam') #spec.convert('photlam') for line in t: if line['f_Ratio'] == 'Atmosphere': continue # #spec += S.GaussianSource(line['Ratio']*4.95e-12, line['Wave']*1., line['Wave']*30./3.e5, fluxunits='photlam') if line['Wave'] == 10830: f = 1.35 else: f = 1. # spec += S.GaussianSource(line['Ratio']*4.95e-12*f, line['Wave']*1., line['Wave']*800./3.e5, fluxunits='photlam') ok = (spec.wave > 7000) & (spec.wave < 1.7e4) np.savetxt('rudy_spec.dat', np.array([spec.wave[ok], spec.flux[ok]]).T, fmt='%.5e')
def _obj_beam_fit(params, beams, x_nodes): """ params = [2.953e-03, 1.156e+00, 1.297e+01, 9.747e-01 , 9.970e-01 , 8.509e-01, 1.076e+00 , 1.487e+00 , 7.864e-01, 1.072e+00 , 1.015e+00] """ import time from scipy.interpolate.fitpack import splev, splrep import pysynphot as S ### Spline continuum + gaussian line l0 = 6563. * (1 + params[1]) if (l0 < 1.12e4) | (l0 > 1.63e4): return -np.inf line = S.GaussianSource(params[2], l0, 10) tck = splrep(x_nodes, params[3:], k=3, s=0) xcon = np.arange(0.9e4, 1.8e4, 0.01e4) ycon = splev(xcon, tck, der=0, ext=0) spec = S.ArraySpectrum(xcon, ycon, fluxunits='flam', keepneg=True) + line lnprob = 0 for key in beams.keys(): beam = beams[key] modelf = beam.compute_model(beam.clip_thumb, xspec=spec.wave, yspec=spec.flux, in_place=False) lnprob += -0.5 * np.sum(((beam.cutout_scif - params[0] - modelf)**2 / beam.cutout_varf)[beam.cutout_maskf]) if ~np.isfinite(lnprob): lnprob = -np.inf print params, lnprob #time.sleep(0.2) return lnprob
def setup_fit(): snlim = 0 snlim = 1. / np.sqrt(len(beams)) Rmax = 5 for key in FLT.keys(): beam = beams[key] beam.cutout_sci = beam.get_cutout(FLT[key].im['SCI'].data) * 1 beam.cutout_dq = beam.get_cutout(FLT[key].im['DQ'].data) * 1 beam.cutout_err = beam.get_cutout(FLT[key].im['ERR'].data) * 1 beam.cutout_mask = (beam.cutout_dq - (beam.cutout_dq & 512) == 0) & ( beam.cutout_err > 0) & (beam.cutout_err < 10) sh = beam.cutout_sci.shape yp, xp = np.indices(beam.thumb.shape) r = np.sqrt((xp - sh[0] / 2)**2 + (yp - sh[0] / 2)**2) beam.norm = beam.thumb[r <= Rmax].sum() / 1.e-17 beam.clip_thumb = beam.thumb * (r <= Rmax) beam.compute_model(beam.clip_thumb) sn = beam.model / beam.cutout_err #beam.mask &= (sn > 0.5) & (beam.err > 0) beam.cutout_mask &= (sn > snlim) & (beam.cutout_err > 0) beam.cutout_sci[~beam.cutout_mask] = 0 beam.cutout_err[~beam.cutout_mask] = 0 beam.cutout_var = beam.cutout_err**2 beam.cutout_scif = beam.cutout_sci.flatten() beam.cutout_varf = beam.cutout_var.flatten() beam.cutout_maskf = beam.cutout_mask.flatten() ds9.view((beam.cutout_scif - beam.cutout_modelf).reshape( beam.cutout_sci.shape) * beam.cutout_mask) ## x_nodes = np.arange(1.0e4, 1.71e4, 0.1e4) x_nodes = np.arange(1.0e4, 1.71e4, 0.03e4) x_nodes = np.arange(1.05e4, 1.71e4, 0.075e4) init = np.append([0, 1.148, 500], np.ones(len(x_nodes))) init = np.append([0, 1.2078, 500], np.ones(len(x_nodes))) step_sig = np.append([0.01, 0.1, 50], np.ones(len(x_nodes)) * 0.1) init = np.append([0, 1.0, 500], np.ones(len(x_nodes))) step_sig = np.append([0.0, 0.2, 150], np.ones(len(x_nodes)) * 0.1) ### don't fit redshift #init = np.append([0, 1.0, 0], np.ones(len(x_nodes))) #step_sig = np.append([0.0,0.,0], np.ones(len(x_nodes))*0.2) obj_fun = _obj_beam_fit obj_args = [beams, x_nodes] ndim, nwalkers = len(init), len(init) * 2 p0 = [(init + np.random.normal(size=ndim) * step_sig) for i in xrange(nwalkers)] NTHREADS, NSTEP = 2, 5 sampler = emcee.EnsembleSampler(nwalkers, ndim, obj_fun, args=obj_args, threads=NTHREADS) # t0 = time.time() result = sampler.run_mcmc(p0, NSTEP) t1 = time.time() print 'Sampler: %.1f s' % (t1 - t0) param_names = ['bg', 'z', 'Ha'] param_names.extend(['spl%d' % i for i in range(len(init) - 3)]) import unicorn.interlace_fit chain = unicorn.interlace_fit.emceeChain(chain=sampler.chain, param_names=param_names) #obj_fun(chain.map, beams) #obj_fun(init, beams, x_nodes) params = chain.map * 1. #params = init ### Show spectra from scipy.interpolate.fitpack import splev, splrep # NDRAW=100 # draw = chain.draw_random(NDRAW) # for i in range(NDRAW): # line = S.GaussianSource(draw[i,2], 6563.*(1+draw[i,1]), 10) # tck = splrep(x_nodes, draw[i,3:], k=3, s=0) # xcon = np.arange(0.9e4,1.8e4,0.01e4) # ycon = splev(xcon, tck, der=0, ext=0) # spec = S.ArraySpectrum(xcon, ycon, fluxunits='flam', keepneg=True)+line # plt.plot(spec.wave, spec.flux, alpha=0.1, color='red') # line = S.GaussianSource(params[2], 6563. * (1 + params[1]), 10) tck = splrep(x_nodes, params[3:], k=3, s=0) xcon = np.arange(0.9e4, 1.8e4, 0.01e4) ycon = splev(xcon, tck, der=0, ext=0) pspec = S.ArraySpectrum(xcon, ycon, fluxunits='flam', keepneg=True) + line for key in beams.keys(): beam = beams[key] beam.compute_model(beam.clip_thumb, xspec=pspec.wave, yspec=pspec.flux, in_place=True) xfull, yfull, mfull, cfull = [], [], [], [] for i, key in enumerate(beams.keys()): beam = beams[key] #ds9.frame(i+1) #ds9.view((beam.sci-beam.model)*beam.mask) ls = 'steps-mid' marker = 'None' #ls = '-' #ls, marker = 'None', '.' xfull = np.append(xfull, beam.lam) ybeam = (beam.cutout_sci - params[0] * beam.cutout_mask).sum( axis=0)[sh[0] / 2:-sh[0] / 2] / beam.ysens / beam.norm yfull = np.append(yfull, ybeam) #plt.plot(beam.lam, ybeam, color='black', alpha=0.5, linestyle=ls, marker=marker) cbeam = ((beam.cutout_m - beam.omodel) * beam.cutout_mask).sum( axis=0)[sh[0] / 2:-sh[0] / 2] / beam.ysens / beam.norm cfull = np.append(cfull, cbeam) mbeam = ((beam.model) * beam.mask).sum( axis=0)[sh[0] / 2:-sh[0] / 2] / beam.ysens / beam.norm mfull = np.append(mfull, mbeam) plt.plot(beam.lam, ybeam - cbeam, color='black', linestyle=ls, alpha=0.5) plt.plot(beam.lam, mbeam, color='blue', linestyle=ls, alpha=0.5) #nx = 20 kern = np.ones(nx) / nx so = np.argsort(xfull) plt.plot(xfull[so][nx / 2::nx], nd.convolve((yfull - cfull)[so], kern)[nx / 2::nx], color='orange', linewidth=2, alpha=0.8, linestyle='steps-mid') plt.plot(xfull[so][nx / 2::nx], nd.convolve(mfull[so], kern)[nx / 2::nx], color='green', linewidth=2, alpha=0.8, linestyle='steps-mid') plt.ylim(0, 5) plt.xlim(1.e4, 1.78e4) from scipy.optimize import fmin_bfgs p0 = fmin_bfgs(_loss, init[3:], args=(beams, x_nodes), gtol=1.e-3, epsilon=1.e-3, maxiter=100) params = np.array(init) params[3:] = p0
def test_symmetry2(self): g = S.GaussianSource(1, 400, 100, 'nm', 'flam') self.assertApproxFP(g.sample(395), g.sample(405))
def test_symmetry1(self): g = S.GaussianSource(1, 4000, 100, 'angstrom', 'photlam') self.assertApproxFP(g.sample(3950), g.sample(4050))
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')
def setUp(self): self.sp = S.BlackBody(60000) + S.GaussianSource(1e-12, 5000, 30)
def setUp(self): self.sp = S.GaussianSource(1e-12, 5000, 30)
def etc_spectra(): """ Make actual spectra for the ETC for the different He bg cases """ import pysynphot as S fl0 = 1.e-17 fwhm = 2 # Angstroms heline = S.GaussianSource(fl0, 1.083e4, fwhm, fluxunits='flam') continuum = S.FlatSpectrum(60, fluxunits='STMag') model_spec = continuum + heline model_spec.convert('flam') bp = S.ObsBandpass('wfc3,ir,f105w') flux = {'50': 0.1, '75': 0.5, '95': 1.5} obs = S.Observation(heline, bp) for key in flux.keys(): fl = fl0 * flux[key] / obs.countrate() print fl fl = fl0 * 1.0 / obs.countrate() #### Normalize to "per arcsec" fl /= 0.1211 * 0.1355 heline = S.GaussianSource(fl, 1.083e4, fwhm, fluxunits='flam') obs = S.Observation(heline, bp) import astropy.io.fits as pyfits h = pyfits.Header() h['CONTACT'] = ('G. Brammer', 'Person to contact in case of questions') h['DESCRIPT'] = ('Airglow line at 10830 A') h['MAPKEY'] = ('el10830a') h['FILE_TYP'] = ('Airglow line at 10830 Angstroms') h['SYSTEMS'] = ('PYETC') h['PSYNEXPR'] = ('GaussianSource(%.3e,1.083e4,%.1f,fluxunits="flam")' % (fl, fwhm)) #h.add_history("This file is a spectrum produced by PySynphot to model the He I 10830 airglow line as a Gaussian with FWHM = 2A. The spectrum is normalized to produce a background countrate of 1 e/s/pix in the WFC3/IR F105W filter.") heline.writefits('el10830a_002.fits', clobber=True) im = pyfits.open('el10830a_002.fits') for card in h.cards: im[0].header[card[0]] = (card[1], card[2]) # im[0].header.add_history( "This file is a spectrum produced by PySynphot to model the He I 10830 airglow line as a Gaussian with FWHM = 2A. The spectrum is normalized to produce a background countrate of 1 e-/s/pix in the WFC3/IR F105W filter." ) im[0].header.add_history("") im[0].header.add_history( "The 50, 75, and 95 percentile fluxes of the line background observed in archival F105W observations are 0.1, 0.5, and 1.5 e/s/pix." ) im[0].header.add_history("") im[0].header.add_history( "For more information on the He 10830 component to the IR background, see WFC3/ISR 2014-03: Time-varying Excess Earth-glow Backgrounds in the WFC3/IR Channel (Brammer et al.)." ) im.writeto('el10830a_002.fits', clobber=True) model_50 = model_spec.renorm(0.1, 'Counts', bp) model_75 = model_spec.renorm(0.5, 'Counts', bp) model_95 = model_spec.renorm(1.5, 'Counts', bp) #### Demo figure plt.plot(model_50.wave - 10830, model_50.flux / 1.e-17, label='F105W 0.1 e/s, 50%') plt.plot(model_75.wave - 10830, model_75.flux / 1.e-17, label='F105W 0.5 e/s, 75%') plt.plot(model_95.wave - 10830, model_95.flux / 1.e-17, label='F105W 1.5 e/s, 95%') plt.xlim(-20, 20) plt.ylabel( r'$f_\lambda$ ($10^{-17}\,\mathrm{erg}\,\mathrm{s}^{-1}\,\mathrm{cm}^{-2}\,\AA^{-1})$' ) plt.xlabel(r'$\lambda - 10830\,\AA$') plt.legend(loc='best', fontsize=12) plt.savefig('He10830_ETC_spec.png') header = """# wavelength flux # Units: (angstroms) (erg/s/cm2/A) # He I 10830 A background component: 50%, 0.1 e/s in F105W # Created: G. Brammer, 2014-09-18 # (made with PySynphot) """ fp = open('HeI_background_50.dat', 'w') fp.write(header) np.savetxt(fp, np.array([model_50.wave, model_50.flux]).T, fmt='%.6e') fp.close() # header = """# wavelength flux # Units: (angstroms) (erg/s/cm2/A) # He I 10830 A background component: 75%, 0.5 e/s in F105W # Created: G. Brammer, 2014-09-18 # (made with PySynphot) """ fp = open('HeI_background_75.dat', 'w') fp.write(header) np.savetxt(fp, np.array([model_75.wave, model_75.flux]).T, fmt='%.6e') fp.close() # header = """# wavelength flux # Units: (angstroms) (erg/s/cm2/A) # He I 10830 A background component: 95%, 1.5 e/s in F105W # Created: G. Brammer, 2014-09-18 # (made with PySynphot) """ fp = open('HeI_background_95.dat', 'w') fp.write(header) np.savetxt(fp, np.array([model_95.wave, model_95.flux]).T, fmt='%.6e') fp.close()
def testRenormSynPysyn(): jv = S.ObsBandpass('johnson,v') acs = S.ObsBandpass('acs,hrc,f555w') abox = S.Box(5500,1) #Removing vegamag from this list because it introduces # a data dependency. Pysynphot has upgraded the version of # vega that it uses for vegamag conversions (11/5/2010, r1629) # but synphot has not. This caused the emission line test # to fail (since the numbers were so small anyway, the small # difference exceeded the tolerance). uset = ['photlam', 'flam', 'photnu', 'fnu', 'jy', 'mjy', 'counts', 'stmag' ,'abmag', 'obmag'] #, 'vegamag' ucounts = ['counts', 'obmag'] bb = S.BlackBody(5000) bb.syndescrip = 'bb(5000)' em = S.GaussianSource(1e-13,5500,250) em.syndescrip = 'em(5500,250,1e-13,flam)' foo = {bb:'bb', em:'em'} rnfuncs = {renorm.StdRenorm:'Std'} #Just this one, # renorm.renormTweak:'tweak', # renorm.renormRevEng:'RevEng' # renorm.renormSVN:'SVN'} - ignore SVN for now, we know it doesn't work for method in rnfuncs: for sp in (bb, em): for u in uset: # ucounts rnunit = Units(u) if u == 'counts': bp = acs bp.syndescrip = "band(%s) " % bp elif rnunit.isMag: bp = jv bp.syndescrip = 'band(johnson,v)' else: bp = abox bp.syndescrip = 'box(5500,1)' def renorm_compare(sp, rnval, rnunits, bp, callable): """Sp and bp must have a special .syndescrip attribute that contains the string needed to make it with synphot""" # Renormalize the spectrum pysyn = callable(sp, bp, rnval, rnunits) #pysyn=sp.renorm(rnval,rnunits,bp) #pysyn = spectrum.StdRenorm(sp,bp,rnval,rnunits) userdir = tempfile.mkdtemp(suffix='pysynphot') old_cwd = os.getcwd() iraf.chdir(userdir) # Make a wavetable and a wavecat fname = "%s.fits" % rnunits pysyn.writefits(fname, clobber=True) wname = "%s.cat" % rnunits f = open(wname, 'w') f.write("box %s\n" % fname) f.close() oname = "syn_%s" % fname try: #Run countrate spstring = "rn(%s,%s,%s,%s) " % (sp.syndescrip, bp.syndescrip, rnval, rnunits) iraf.countrate(spectrum=spstring, magnitude="", instrument="box(15000,30000)", form=str(pysyn.fluxunits), wavecat=wname, output=oname) syn = S.FileSpectrum(oname) # Check that they have the same shape and fluxunits assert (syn.flux.shape == pysyn.flux.shape) assert (type(syn.fluxunits) == type(pysyn.fluxunits)) # Now a real test idx = np.where(syn.flux != 0) rat = (syn.flux[idx] / pysyn.flux[idx]) q = abs(1 - rat[2:-2]) qtrunc = (10**4*q).astype(np.int) assert np.alltrue(qtrunc < 110), \ "Min/max ratio = %f,%f" % (q.min(),q.max()) finally: iraf.chdir(old_cwd) shutil.rmtree(userdir) renorm_compare.description = ( "%s.test%s_%s_%s" % (__name__, rnfuncs[method], foo[sp], u)) yield renorm_compare, sp, 10, u, bp, method
def setUp(self): self.sp=S.GaussianSource(1e14,10000,10)