def modified_BB_draine2007beta_z(nu, param): """ Formula of modified black body to link dust mass and beta (and kappa), without an extra normalisation factor """ import astropy.constants as cst from astropy.cosmology import Planck15 # from astropy import analytic_functions import astropy.units as u from astropy.modeling import models mdust, tdust, beta, redshift = param bb = models.BlackBody1D(tdust * u.K, bolometric_flux=cst.L_sun.to(u.erg / u.s) / (u.cm * u.cm)) nu_rest = nu * (1 + redshift) * u.Hz # shift the frequency range to restframe nu_0 = (cst.c / (250e-6 * u.m)).to(u.Hz) kappa_n0 = 4.0 * u.cm * u.cm / u.g kappa_abs = kappa_n0.to(u.m * u.m / u.kg) * (nu_rest / nu_0)**beta DL = Planck15.luminosity_distance(redshift) y_z = bb(nu_rest) * (1 + redshift) * kappa_abs.to(u.cm * u.cm / u.kg) y_z *= ((10**mdust) * u.M_sun).to(u.kg) * u.kg y_z /= (DL.to(u.cm) * DL.to(u.cm) * cst.M_sun) return y_z.value
def bbfunc(x,*par): """ Helper function for gettempbb. Initialize a blackbody model without values. """ import astropy.units as ur from astropy.modeling import models from astropy.modeling.blackbody import FLAM temp,norm = par mod = models.BlackBody1D(temperature=temp*ur.K,bolometric_flux = norm*ur.erg/(ur.cm**2 * ur.s)) return mod(x*ur.nm).to(FLAM, equivalencies=ur.spectral_density(x*ur.nm)).value
T_dust = 130. * u.Kelvin F_ir = 10**(-10.6) * (u.erg / u.cm / u.cm / u.s) # read in the spectrum sp = ascii.read(data_dir + f) #change the unit on the wavelength axis to work with astropy sp['wavelength'].unit = u.micron # plot fig, (ax1, ax2) = plt.subplots(2, 1, figsize=[12, 6]) ax1.plot(sp['wavelength'], sp['flux_density'], label='Spitzer merged spectrum') ax1.set_xlabel('wavelength (micron)') ax1.set_ylabel('flux (Jy)') # now fit the continuum bb = models.BlackBody1D(temperature=T_dust, bolometric_flux=F_ir) ax1.plot(sp['wavelength'], bb(sp['wavelength']).to(u.Jy), 'r-', label='best fit BB (T = 130 K)') ax1.set_title('SMP LMC 81') ax1.legend(loc=2) # subtract best-fit BB from spectrum sp_sub = sp['flux_density'] - bb(sp['wavelength']).to(u.Jy) ax2.plot(sp['wavelength'], sp_sub, label='spectrum, continuum subtracted') ax2.set_xlabel('wavelength (micron)') ax2.set_ylabel('flux (Jy)') #ax2.set_xlim((5., 15.)) ax2.legend(loc=2) fig.show()
def bb_abmag_fluence(val=False, duet=None, **kwargs): """ Take a blackbody with a certain temperature and convert to photon rate in a band. Other Parameters ---------------- val : boolean Retrurns AB mags without units (False, default) or with Astropy units duet: ``astroduet.conifg.Telescope() object`` If you've already instanced a duet telecope object, feed it in here. Currently allows the use of the default bandpasses. umag : float Must have astropy AB units Apparent U-band AB mag. Only used if other values not provided? siwftmag : float Must have astropy AB units. Apparent Swift magnitude (default is 22*u.ABmag) ref : string Band to use for reference magnitude; options are 'u', 'swift' ('swift') bbtemp : float Blackbody temperature to use (20000*ur.K) dist : float Distance of the source. swiftmags are assumed to be given at a reference distance of 10 pc (I think?) bolflux : float Bolometric flux; if not 1, refmag and distance are ignored. Should have units like (1*ur.erg/ur.cm**2/ur.s) diag : boolean SHow diagnostic inforamtion Returns ------- ABmag1, ABmag2 """ import astropy.units as ur import astropy.constants as cr from astropy.modeling import models from astropy.modeling.blackbody import FLAM import numpy as np from astroduet.config import Telescope if duet is None: duet = Telescope() bbtemp = kwargs.pop('bbtemp', 20000. * ur.K) umag = kwargs.pop('umag', 22 * ur.ABmag) swiftmag = kwargs.pop('swiftmag', 22 * ur.ABmag) dist = kwargs.pop('dist', 10 * ur.pc) ref = kwargs.pop('ref', 'swift') diag = kwargs.pop('diag', False) dist0 = 10 * ur.pc bolflux = kwargs.pop('bolflux', 1. * ur.erg / (ur.cm**2 * ur.s)) bandu = [340, 380] * ur.nm # For comparison purposes bandsw = [ 172.53, 233.57 ] * ur.nm # Swift UVW2 effective band (lambda_eff +/- 0.5 width_eff) wav = np.arange(1000, 9000) * ur.AA # Wavelength scale in 1 Angstrom steps bb = models.BlackBody1D( temperature=bbtemp, bolometric_flux=bolflux) # Load the blackbody model flux = bb(wav).to(FLAM, ur.spectral_density(wav)) # Get Swift reference AB mag fluxden_sw = np.mean(flux[(wav >= bandsw[0].to(ur.AA)) & (wav <= bandsw[1].to(ur.AA))]) magsw = fluxden_sw.to(ur.ABmag, equivalencies=ur.spectral_density(np.mean(bandsw))) # Conver to flux AB mags across the band. flux_ab = flux.to(ur.ABmag, equivalencies=ur.spectral_density(wav)) # Distance modulus distmod = (5 * np.log10(dist / dist0)).value * ur.mag # Set up input: magoff = swiftmag - magsw # Apply the distance modulus and the Swift reference offset if (bolflux == 1. * ur.erg / (ur.cm**2 * ur.s)): flux_mag = flux_ab + magoff + distmod else: flux_mag = flux_ab # Convert back to flux flux_conv = flux_mag.to(FLAM, equivalencies=ur.spectral_density(wav)) dw = 1 * ur.AA ph_energy = (cr.h.cgs * cr.c.cgs / wav.cgs) / ur.ph # Convert to photon flux. ph_flux = flux_conv * dw / ph_energy # Apply filters, QE, etc. band1_fluence = duet.apply_filters(wav, ph_flux, diag=diag, **kwargs).sum() band2_fluence = duet.apply_filters(wav, ph_flux, band=2, diag=diag, **kwargs).sum() if diag: print() print('Compute ABmags in TD bands for blackbody') print('Blackbody temperature: {}'.format(bbtemp)) print('Reference UVW2-band magnitude: {}'.format(swiftmag)) print('Distance: {} (Reference distance is 10 pc)'.format(dist)) print() print('Flux density Swift: {}'.format(fluxden_sw)) print('Distance modulus: {}'.format(distmod)) print('Raw ABmag Swift: {}'.format(magsw)) print('Offset from Swift band: {}'.format(magoff)) print('Fluence band one: {}'.format(band1_fluence)) print('Fluence band two: {}'.format(band2_fluence)) print('') if val: return band1_fluence.value, band2_fluence.value else: return band1_fluence, band2_fluence
def bb_abmag(diag=False, val=False, **kwargs): """ Take a blackbody with a certain temperature and convert to AB magnitudes in two bands. Scaled to u-band or Swift UVW2 magnitude. Inputs (defaults): umag = apparent u-band AB magnitude (22*ur.ABmag) swiftmag = apparent Swift UVW2 magnitude (22*ur.ABmag) ref = band to use for reference magnitude; options are 'u', 'swift' ('swift') bandone = Bandpass 1st filter (180-220)*ur.nm bandtwo = Bandpass 2nd filter (260-300)*ur.nm bbtemp = Blackbody temperature (20000*ur.K) dist = Distance (10*ur.pc) val = Return values without unit if True (False) bolflux = Bolometric flux; if not 1, refmag and distance are ignored (1*ur.erg/ur.cm**2/ur.s) diag (False) Returns ABmag1, ABmag2 """ import astropy.units as ur import astropy.constants as cr from astropy.modeling import models from astropy.modeling.blackbody import FLAM import numpy as np bbtemp = kwargs.pop('bbtemp', 20000. * ur.K) bandone = kwargs.pop('bandone', [180, 220] * ur.nm) bandtwo = kwargs.pop('bandtwo', [260, 300] * ur.nm) umag = kwargs.pop('umag', 22 * ur.ABmag) swiftmag = kwargs.pop('swiftmag', 22 * ur.ABmag) dist = kwargs.pop('dist', 10 * ur.pc) ref = kwargs.pop('ref', 'swift') dist0 = 10 * ur.pc bolflux = kwargs.pop('bolflux', 1. * ur.erg / (ur.cm**2 * ur.s)) bandu = [340, 380] * ur.nm # For comparison purposes bandsw = [ 172.53, 233.57 ] * ur.nm # Swift UVW2 effective band (lambda_eff +/- 0.5 width_eff) wav = np.arange(1000, 9000) * ur.AA # Wavelength scale in 1 Angstrom steps bb = models.BlackBody1D( temperature=bbtemp, bolometric_flux=bolflux) # Load the blackbody model flux = bb(wav).to(FLAM, ur.spectral_density(wav)) # Calculate mean flux density in each band: fluxden_one = np.mean(flux[(wav >= bandone[0].to(ur.AA)) & (wav <= bandone[1].to(ur.AA))]) fluxden_two = np.mean(flux[(wav >= bandtwo[0].to(ur.AA)) & (wav <= bandtwo[1].to(ur.AA))]) fluxden_u = np.mean(flux[(wav >= bandu[0].to(ur.AA)) & (wav <= bandu[1].to(ur.AA))]) fluxden_sw = np.mean(flux[(wav >= bandsw[0].to(ur.AA)) & (wav <= bandsw[1].to(ur.AA))]) # Convert to AB magnitudes: magone = fluxden_one.to(ur.ABmag, equivalencies=ur.spectral_density( np.mean(bandone))) magtwo = fluxden_two.to(ur.ABmag, equivalencies=ur.spectral_density( np.mean(bandtwo))) magu = fluxden_u.to(ur.ABmag, equivalencies=ur.spectral_density(np.mean(bandu))) magsw = fluxden_sw.to(ur.ABmag, equivalencies=ur.spectral_density(np.mean(bandsw))) if (ref == 'u'): # Offset from comparison u-band magnitude: magoff = umag - magu elif (ref == 'swift'): # Offset from comparison swift UVW2-band magnitude: magoff = swiftmag - magsw # Distance modulus distmod = (5 * np.log10(dist / dist0)).value * ur.mag # Apply offsets magone_final = magone + magoff + distmod magtwo_final = magtwo + magoff + distmod if (bolflux == 1. * ur.erg / (ur.cm**2 * ur.s)): magone_final = magone + magoff + distmod magtwo_final = magtwo + magoff + distmod else: magone_final = magone magtwo_final = magtwo if diag: print() print('Compute ABmags in TD bands for blackbody') print('Blackbody temperature: {}'.format(bbtemp)) print('Reference UVW2-band magnitude: {}'.format(swiftmag)) print('Band one: {}'.format(bandone)) print('Band two: {}'.format(bandtwo)) print('Distance: {}'.format(dist)) print('Flux density band one: {}'.format(fluxden_one)) print('Flux density band two: {}'.format(fluxden_two)) print('Flux density Swift: {}'.format(fluxden_sw)) print('Distance modulus: {}'.format(distmod)) print('Raw ABmag band one: {}'.format(magone)) print('Raw ABmag band two: {}'.format(magtwo)) print('Raw ABmag Swift: {}'.format(magsw)) print('Offset from Swift band: {}'.format(magoff)) print('ABmag band one: {}'.format(magone_final)) print('ABmag band two: {}'.format(magtwo_final)) print('') if val: return magone_final.value, magtwo_final.value else: return magone_final, magtwo_final
def bb_abmag_fluence(val=False, **kwargs): """ Take a blackbody with a certain temperature and convert to photon rate in a band. Now applies the various filters and returns *photon fluence* in the band Now also accepts bolometric flux as input. Inputs (defaults): umag = apparent u-band AB magnitude (22*ur.ABmag) swiftmag = apparent Swift UVW2 magnitude (22*ur.ABmag) ref = band to use for reference magnitude; options are 'u', 'swift' ('swift') bandone = Bandpass 1st filter (180-220)*ur.nm bandtwo = Bandpass 2nd filter (260-300)*ur.nm bbtemp = Blackbody temperature (20000*ur.K) dist = Distance (10*ur.pc) val = Return values without unit if True (False) bolflux = Bolometric flux; if not 1, refmag and distance are ignored (1*ur.erg/ur.cm**2/ur.s) diag (False) Returns ABmag1, ABmag2 Also still to do: Add background from galaxies. """ import astropy.units as ur import astropy.constants as cr from astropy.modeling import models from astropy.modeling.blackbody import FLAM import numpy as np from tdsat_telescope import apply_filters bbtemp = kwargs.pop('bbtemp', 20000. * ur.K) # bandone = kwargs.pop('bandone', [180,220]*ur.nm) # bandtwo = kwargs.pop('bandtwo', [260,300]*ur.nm) umag = kwargs.pop('umag', 22 * ur.ABmag) swiftmag = kwargs.pop('swiftmag', 22 * ur.ABmag) dist = kwargs.pop('dist', 10 * ur.pc) ref = kwargs.pop('ref', 'swift') diag = kwargs.pop('diag', False) dist0 = 10 * ur.pc bolflux = kwargs.pop('bolflux', 1. * ur.erg / (ur.cm**2 * ur.s)) bandu = [340, 380] * ur.nm # For comparison purposes bandsw = [ 172.53, 233.57 ] * ur.nm # Swift UVW2 effective band (lambda_eff +/- 0.5 width_eff) wav = np.arange(1000, 9000) * ur.AA # Wavelength scale in 1 Angstrom steps bb = models.BlackBody1D( temperature=bbtemp, bolometric_flux=bolflux) # Load the blackbody model flux = bb(wav).to(FLAM, ur.spectral_density(wav)) # Get Swift reference AB mag fluxden_sw = np.mean(flux[(wav >= bandsw[0].to(ur.AA)) & (wav <= bandsw[1].to(ur.AA))]) magsw = fluxden_sw.to(ur.ABmag, equivalencies=ur.spectral_density(np.mean(bandsw))) # Conver to flux AB mags across the band. flux_ab = flux.to(ur.ABmag, equivalencies=ur.spectral_density(wav)) # Distance modulus distmod = (5 * np.log10(dist / dist0)).value * ur.mag # Set up input: magoff = swiftmag - magsw # Apply the distance modulus and the Swift reference offset if (bolflux == 1. * ur.erg / (ur.cm**2 * ur.s)): flux_mag = flux_ab + magoff + distmod else: flux_mag = flux_ab # Convert back to flux flux_conv = flux_mag.to(FLAM, equivalencies=ur.spectral_density(wav)) dw = 1 * ur.AA ph_energy = (cr.h.cgs * cr.c.cgs / wav.cgs) # Convert to photon flux. ph_flux = flux_conv * dw / ph_energy # Apply filters, QE, etc. band1_fluence = apply_filters(wav, ph_flux, diag=diag, **kwargs).sum().sum() band2_fluence = apply_filters(wav, ph_flux, band=2, diag=diag, **kwargs).sum() if diag: print() print('Compute ABmags in TD bands for blackbody') print('Blackbody temperature: {}'.format(bbtemp)) print('Reference UVW2-band magnitude: {}'.format(swiftmag)) print('Distance: {} (Reference distance is 10 pc)'.format(dist)) print() print('Flux density Swift: {}'.format(fluxden_sw)) print('Distance modulus: {}'.format(distmod)) print('Raw ABmag Swift: {}'.format(magsw)) print('Offset from Swift band: {}'.format(magoff)) print('Fluence band one: {}'.format(band1_fluence)) print('Fluence band two: {}'.format(band2_fluence)) print('') if val: return band1_fluence.value, band2_fluence.value else: return band1_fluence, band2_fluence
def filter_parameters(duet=None, *args, **kwargs): """ Construct the effective central wavelength and the effective bandpass for the filters. Parameters ---------- Other parameters ---------------- vega : conditional, default False Use the Vega spetrum (9.8e3 K blackbody) to compute values. Otherwise computed "flat" values if quoting AB mags. diag : conditional, default False Show the diagnostic info on the parameters. Examples -------- >>> band1, band2 = filter_parameters() >>> allclose(band1['eff_wave'].value, 198.63858525) True """ from astroduet.config import Telescope if duet is None: duet = Telescope() from astropy.modeling import models from astropy.modeling.blackbody import FNU, FLAM from astropy import units as u import numpy as np vega = kwargs.pop('vega', False) diag = kwargs.pop('diag', False) wave = np.arange(1000, 10000) * u.AA if vega: temp = 9.8e3 * u.K bb = models.BlackBody1D(temperature=temp) flux = bb(wave).to(FLAM, u.spectral_density(wave)) else: flat_model = np.zeros_like(wave.value) flat_model += 1 flat_model *= FNU flux = flat_model.to(FLAM, u.spectral_density(wave)) band1 = duet.apply_filters(wave, flux, band=1, **kwargs) band2 = duet.apply_filters(wave, flux, band=2, **kwargs) λ_eff1 = ((band1 * wave).sum() / (band1.sum())).to(u.nm) λ_eff2 = ((band2 * wave).sum() / (band2.sum())).to(u.nm) dλ = wave[1] - wave[0] t1 = band1 / flux t2 = band2 / flux w1 = (dλ * t1.sum() / t1.max()).to(u.nm) w2 = (dλ * t2.sum() / t2.max()).to(u.nm) band1 = {'eff_wave': λ_eff1, 'eff_width': w1} band2 = {'eff_wave': λ_eff2, 'eff_width': w2} if diag: print('Band1: {0:0.2f} λ_eff, {1:0.2f} W_eff'.format(λ_eff1, w1)) print('Band2: {0:0.2f} λ_eff, {1:0.2f} W_eff'.format(λ_eff2, w2)) return band1, band2