def setUp(self): # Make Spectrum class for testing WAVE1 = np.linspace(0.8, 2.5, 200) * q.um FLUX1 = blackbody_lambda(WAVE1, 3000 * q.K) * q.sr SPEC1 = [WAVE1, FLUX1, FLUX1 / 100.] self.spec1 = sp.Spectrum(*SPEC1) # Make another WAVE2 = np.linspace(21000, 38000, 150) * q.AA FLUX2 = blackbody_lambda(WAVE2, 6000 * q.K) * q.sr SPEC2 = [WAVE2, FLUX2, FLUX2 / 100.] self.spec2 = sp.Spectrum(*SPEC2) self.sed = sed.SED()
def calc_shk(lamGrid, targOlapf, rvcc, teff=6200.): from helpers import hk_windows import helpers as h #for constants from astropy.modeling.blackbody import blackbody_lambda from astropy import units as u from matplotlib import pyplot as plt gain = 3.4 # e-/ADU kk = 31. # factor to make shk into equivalent width (a guess!) #this function gives us the regions of our arrays which hold the information we need to sum windows = hk_windows(rvcc, lamGrid, h.cahLam, h.cakLam, h.lamB, h.lamR)[0] fh = (targOlapf * windows[:, 0]).sum() fk = (targOlapf * windows[:, 1]).sum() fr = (targOlapf * windows[:, 2]).sum() #plt.figure() #cur=windows[:,0] #plt.plot(lamGrid[cur!=0],targOlapf[cur!=0])#*cur[cur!=0],'k-') #plt.show() #plt.close() #plt.figure() #cur=windows[:,1] #plt.plot(lamGrid[cur!=0],targOlapf[cur!=0])#*cur[cur!=0],'k-') #plt.show() #plt.close() #plt.figure() #cur=windows[:,2] #plt.plot(lamGrid[cur!=0],targOlapf[cur!=0])#*cur[cur!=0],'k-') #plt.show() #plt.close() #the SHK calculation with pseudo V-Band plFactor = blackbody_lambda(h.lamB * u.nm, teff * u.K).value / blackbody_lambda( h.lamR * u.nm, teff * u.K).value fb = fr * plFactor num = (fh + fk) * gain den = (fr + fb) * gain shk = kk * (fh + fk) / (fr + fb) #print("shk: "+ str(shk)) return shk, windows, fr / fb
def sed(temp: float, wavelengths: np.array, pwv: float, bins: Union[int, list, np.ndarray] = None): """Return the flux of a black body under the influence of pwv absorption Flux is returned in units of ergs / (angstrom * cm2 * s). Args: temp: The temperature of the black body in Kelvin wavelengths: The SED's wavelengths in Angstroms pwv: The PWV concentration along line of sight in mm bins: Integer number of bins or sequence of bin edges used to smooth atmospheric transmission Returns: An array of flux values in units of ergs / (angstrom * cm2 * s * sr) """ # blackbody_lambda returns ergs / (angstrom * cm2 * s * sr) bb_sed = blackbody_lambda(wavelengths, temp).value if pwv > 0: transmission = trans_for_pwv(pwv, bins=bins) sampled_transmission = np.interp(wavelengths, transmission['wavelength'], transmission['transmission']) bb_sed *= sampled_transmission return bb_sed
def planck(data,temp,sr_o,key = 'wave'): sr = sr_o*u.sr ### Setting Steradian temperature = temp * u.K if key == 'wave': wave = [x*10 for x in data] # change the wavelength nm to Angstrom dw = 1 d_w = dw*u.AA wavelengths = np.arange(wave[0], wave[1],dw) * u.AA flux_lam = blackbody_lambda(wavelengths, temperature) flux_lam_f = flux_lam*sr flux_wat = flux_lam_f.to(u.W/u.cm**2/u.AA) # Change the blackbody intensity to "Wats/cm^2/A" flux_lam_p = flux_lam_f*wavelengths/(h*c) # The number of photons flux_lam_p = flux_lam_p.to(u.m**-2/u.AA/u.s) total_flux_photon = sum(flux_lam_p)*d_w elif key == 'hertz': dnu = 1e12 d_nu = dnu*u.Hz nu = np.arange(data[0],data[1],dnu)*u.Hz flux_nu = blackbody_nu(nu, temperature) flux_nu_f = flux_nu*sr flux_wat = flux_nu_f.to(u.W/u.cm**2/u.Hz) # Change the blackbody intensity to "Wats/cm^2/A" flux_nu_p = flux_nu_f/(h*nu) # The number of photons flux_nu_p = flux_nu_p.to(u.cm**-2/u.Hz/u.s) total_flux_photon = sum(flux_nu_p)*d_nu else: print "Please re-input the right key" return total_flux_photon,flux_wat
def blackbodyFlux(w, T, w_units=u.micron): ''' Returns the spectral flux density (per unit wavelength) for a blackbody at temperature T, over wavelengths w. Wrapper for astropy.modelinig.blackbody.blackbody_lambda Parameters: w (float or array): wavelengths to evalualte B_lambda over T (float): Temperature of blackbody w_units (float or astropy.units.core.Unit): Units of wavelength If float, considered as prefix relative to meters i.e. 1 - meters 10e-6 - microns 10e-9 - nanometers Returns: B_lambda (same as w): spectral radiance per unit wavelength for input wavelengths units: erg cm^-2 s^-1 w_unit^-1 ''' # assert w has units w = assertUnits(w, w_units, u.m) u_radiance = u.erg / (u.s * u.sr * u.cm**2) u_spec_rad = u_radiance / (w_units) spec_rad = blackbody_lambda(w, T).to(u_spec_rad) spec_flux_dens = spec_rad * np.pi * u.sr return spec_flux_dens
def bb_min(params, specphot, filters, wavelength, verbose=False): T = params["T"] flux_scale = params["flux_scale"] EBV = params["EBV"] if verbose: print(type(u.AA)) bb_wavelength = np.array(wavelength) * u.AA bb_flux = bb.blackbody_lambda(bb_wavelength, temperature=T*u.Kelvin) # bb_flux = bb.blackbody_lambda(bb_wavelength, temperature=T*u.Kelvin) bb_spec = classes.SpectrumClass() bb_spec.load_table(Table([wavelength, bb_flux], names=("wavelength", "flux"))) bb_spec.flux = extinction.unred(bb_spec.wavelength, bb_spec.flux, EBV=EBV) bb_spec.data["flux"] = bb_spec.data["flux"] / flux_scale bb_spec.flux = bb_spec.flux / flux_scale bb_spec.get_specphot(filters, verbose=verbose) residual = specphot["flux"] - bb_spec.specphot["flux"] # return np.sum((residual)**2) return residual
def _calculate_photosphere_luminosity(self, packets_mode): """ Calculate blackbody luminosity of the photosphere. Parameters ---------- packets_mode : {'virtual', 'real'} Mode of packets to be considered, either real or virtual Returns ------- astropy.Quantity Luminosity density lambda (or Flux) of photosphere (inner boundary of TARDIS simulation) """ L_lambda_ph = ( abb.blackbody_lambda( self.plot_wavelength, self.data[packets_mode].t_inner, ) * 4 * np.pi ** 2 * self.data[packets_mode].r_inner[0] ** 2 * u.sr ).to("erg / (AA s)") return L_lambda_ph / self.lum_to_flux
def do_respcorr(inspec, respcorr, respfile=None, Tstar=1.e4, doplot=True, **kwargs): """ Does a response correction. The default behavior, which occurs when respcorr is 'model', involves generating a set of blackbody curves over the wavelength ranges of the input spectra and then multiplying the spectra by those curves. This should work because the assumption is that the input spectra have already been divided by the standard to correct for the atmosphere. """ if respcorr == 'model': for spec in inspec: bbspec = blackbody_lambda(spec['wav'], Tstar).value spec.resp_corr(bbspec, mode='atmcorr') else: print('') print("NOTE: only respcorr='model' allowed at this time") print('') return
def inject_microflares(wavelengths, times, seed=None): """ Inject flares into a transit light curve at ``times`` at ``wavelengths`` Model the flare rate as a Poisson process with rate parameter set by the K2 flare frequency - 11 flares in 78.8 days. Draw random variates from that Poisson distribution and assign properties to the flares from the K2 observations. Assume a 10000 K blackbody for flares. Parameters ---------- times : `~numpy.ndarray` Times of observations Returns ------- fluxes : `~numpy.ndarray` Fluxes with flares added. """ total_flux = inject_microflares_total_flux(times, seed=seed) bb = blackbody_lambda(wavelengths, 10000).value bb_flux_total = np.sum(bb) # total flux from flare in bandpass return bb / bb_flux_total * total_flux[:, np.newaxis]
def _generate_photosphere_part(self): """generate the photospheric input spectrum part of the Kromer plot""" Lph = (abb.blackbody_lambda(self.mdl.spectrum_wave, self.mdl.t_inner) * 4 * np.pi**2 * self.mdl.R_phot**2 * units.sr).to("erg / (AA s)") self.ax.plot(self.mdl.spectrum_wave, Lph, color="red", ls="dashed")
def get_thermal_emission(self, wvs, band="TwoMass-J"): ''' The telescope emission as a function of wavelength Outputs: thermal_emission - usnits of photons/s/cm**2/angstrom ''' diffraction_limit = (wvs / self.diameter.to(u.micron) * u.radian).to( u.arcsec) solidangle = diffraction_limit**2 * 1.13 # TODO: blackbody_lambda is deprecated, change to BlackBody #bb_lam = BlackBody(self.temperature,scale=1.0*u.erg/(u.cm**2*u.AA*u.s*u.sr)) #inst_therm = bb_lam(wvs) thermal_emission = blackbody_lambda(wvs, self.temperature) thermal_emission *= solidangle thermal_emission = thermal_emission.to( u.ph / (u.s * u.cm**2 * u.AA), equivalencies=u.spectral_density(wvs)) thermal_emission *= self.get_telescope_emissivity(wvs, band=band) return thermal_emission
def evaluate(self, x, temp, norm): """ Evaluate the blackbody for a given temperature over a wavelength range. Parameters ---------- x: numpy.ndarray The wavelengths to evaulate over. temp: float The temperature to evualate at. norm: float The normalization factor. Returns ------- blackbody_flux: numpy.ndarray The blackbody flux. """ # x is passed as a bare numpy array; must be # converted back to Quantity before calling # astropy's black body functions. _x_u = x * self.wave.unit # convert result of the Planck function to # flux density in the same units as the data. _flux = (blackbody_lambda(_x_u, temp) * u.sr).to(self.flux.unit) # normalize and return just the values, # to conform to the Model API. return (norm * _flux).value
def blackbody(wavelengths, temperature=5777, norm=1): """ Return a blackbody curve for `wavelengths` with a given `temperature` (default: 5777, effective temperature of the Sun), normalised to a maximum value of `norm`. """ bb = blackbody_lambda(wavelengths*10, temperature).value bb = bb / bb.max() * norm return bb
def BC_flux(self, spectrum=None, parameters=None): """ Analytic model of the BalmerContinuum (BC) based on Grandi et al. (1982) and Kovacevic & Popovic (2013). F(lambda) = F(3646 A) * B(T_e) * (1 - e^-tau(lambda)) tau(lambda) = tau(3646) * (lambda/3646)^3 This component has 5 parameters: parameter1 : The flux normalization at the Balmer Edge lambda = 3646 A, F(3646) parameter2 : The electron temperture T_e for the Planck function B(T_e) parameter3 : The optical depth at the Balmer edge, tau(3646) parameter4 : A shift of the line centroids parameter5 : The width of the Gaussians note that all constants, and the units, are absorbed in the parameter F(3646 A). To impliment this appropriately, the planck function is normalized at 3646 A, so that F(3646) actually represents the flux at this wavelength. priors: p1 : Flat between 0 and the measured flux at 3466 A. p2 : Flat between 5 000 and 20 000 Kelvin p3 : Flat between 0.1 and 2.0 p4 : Determined from Hbeta, if applicable. p5 : Determined from Hbeta, if applicable. """ #get the parameters normalization = parameters[self.parameter_index("bc_norm")] Te = parameters[self.parameter_index("bc_Te")] tauBE = parameters[self.parameter_index("bc_tauBE")] loffset = parameters[self.parameter_index("bc_loffset")] lwidth = parameters[self.parameter_index("bc_lwidth")] logNe = parameters[self.parameter_index("bc_logNe")] # Wavelength at which Balmer components merge. edge_wl = balmer_edge * (1 - loffset / c.value) #TODO need WL as quantity objects for better astropy functionality blackbody = blackbody_lambda(spectrum.wavelengths, Te) #calculates [1 - e^(-tau)] (optically-thin emitting slab) #assumes angstroms tau = tauBE * (spectrum.wavelengths / balmer_edge)**3 absorption = 1 - np.exp(-tau) bc_flux = absorption * blackbody bc_flux = self.log_conv(spectrum.wavelengths, bc_flux, lwidth / c.value) norm_index = find_nearest_index(spectrum.wavelengths, edge_wl) fnorm = bc_flux[norm_index] bc_flux[spectrum.wavelengths > spectrum.wavelengths[norm_index]] = 0. bc_flux *= normalization / fnorm return bc_flux
def test_blackbody_overflow(): """Test Planck function with overflow.""" photlam = u.photon / (u.cm**2 * u.s * u.AA) wave = [0, 1000.0, 100000.0, 1e55] # Angstrom temp = 10000.0 # Kelvin with np.errstate(all='ignore'): bb_lam = blackbody_lambda(wave, temp) * u.sr flux = bb_lam.to(photlam, u.spectral_density(wave * u.AA)) / u.sr # First element is NaN, last element is very small, others normal assert np.isnan(flux[0]) assert np.log10(flux[-1].value) < -134 np.testing.assert_allclose( flux.value[1:-1], [3.38131732e+16, 3.87451317e+15], rtol=1e-3) # 0.1% accuracy in PHOTLAM/sr with np.errstate(all='ignore'): flux = blackbody_lambda(1, 1e4) assert flux.value == 0
def calc_brightness_ratio_from_Teff(Teff_1, Teff_2, plot=False): bandpass = np.genfromtxt('tess-response-function-v1.0.csv', delimiter=',', names=['wavelength','transmission']) wavelength_grid = np.arange(500,2000,1) if plot: fig, ax = plt.subplots() ax.plot(list(bandpass['wavelength'])+[2000], list(bandpass['transmission'])+[0], lw=2) ax.set(ylabel='TESS Transmission') ax2 = ax.twinx() ax2.plot(wavelength_grid, blackbody_lambda(wavelength_grid*u.nm, Teff_1*u.K), 'r-', lw=2, color='darkorange') ax2.plot(wavelength_grid, blackbody_lambda(wavelength_grid*u.nm, Teff_2*u.K), 'r-', lw=2, color='brown') ax2.set(ylabel='Blackbody Flux\n'+r'($erg \, cm^{-2} \, s^{-1} \, A^{-1} \, sr^{-1}$)') int1 = np.trapz(bandpass['transmission']*u.nm*blackbody_lambda(bandpass['wavelength']*u.nm, Teff_1*u.K), x=bandpass['wavelength']*u.nm, dx=np.diff(bandpass['wavelength']*u.nm)) int2 = np.trapz(bandpass['transmission']*u.nm*blackbody_lambda(bandpass['wavelength']*u.nm, Teff_2*u.K), x=bandpass['wavelength']*u.nm, dx=np.diff(bandpass['wavelength']*u.nm)) sbratio = int2/int1 return sbratio
def test_zero_pwv(self): """Tests returned SED has no atmospheric features for pwv = 0""" returned_sed = sed(self.temp, self.wavelengths, 0) expected_sed = blackbody_lambda(self.wavelengths, self.temp).value sed_is_same = np.all(np.equal(returned_sed, expected_sed)) self.assertTrue(sed_is_same, "SED does not match ideal black body for pwv = 0")
def test_blackbody_overflow(): """Test Planck function with overflow.""" photlam = u.photon / (u.cm**2 * u.s * u.AA) wave = [0, 1000.0, 100000.0, 1e55] # Angstrom temp = 10000.0 # Kelvin with np.errstate(all='ignore'): bb_lam = blackbody_lambda(wave, temp) * u.sr flux = bb_lam.to(photlam, u.spectral_density(wave * u.AA)) / u.sr # First element is NaN, last element is very small, others normal assert np.isnan(flux[0]) assert np.log10(flux[-1].value) < -134 np.testing.assert_allclose( flux.value[1:-1], [3.38131732e+16, 3.87451317e+15], rtol=1e-3) # 0.1% accuracy in PHOTLAM/sr with np.errstate(all='ignore'): flux = blackbody_lambda(1, 1e4) assert flux.value == 0
def bb_correct(teff, w_phoenix, f_phoenix): """ addition to intergrated flux to calculate bolometric flux. Needs scaled Phoenix flux """ bb_flux = blackbody_lambda(w_phoenix, teff)*u.sr int_phoenix = np.trapz(f_phoenix, w_phoenix) int_bb = np.trapz(bb_flux, w_phoenix) scale = int_phoenix/int_bb bolometric_flux = (const.sigma_sb * teff ** 4 / np.pi).to(u.erg / (u.cm * u.cm * u.s)) flux_correct = (bolometric_flux.value * scale.value) - int_phoenix return flux_correct
def calc_flux(wave, amp, temp): """ Calculates blackbody flux as a function of wavelength (um) and temperature (K). Args: wave : Wavelength (In Angstroms) amp : Amplitude of the blackbody flux temp : Temperature (In Kelvin) Returns: units of erg/s/cm^2/Angstrom """ return amp * blackbody_lambda(in_x=np.asarray(wave), temperature=temp).value
def blackbody(wavelength, temperature=2000): """ Generate a blackbody of the given temperature at the given wavelengths Parameters ---------- wavelength: array-like The wavelength array [um] temperature: float The temperature of the star [K] Returns ------- astropy.quantity.Quantity The blackbody curve """ wavelength = q.Quantity(wavelength, "um") temperature = q.Quantity(temperature, "K") max_val = blackbody_lambda((ac.b_wien/temperature).to(q.um), temperature).value return blackbody_lambda(wavelength, temperature).value/max_val
def __init__(self, T_eff, radius, distance): """ Parameters ---------- T_eff : `~astropy.units.Quantity` Effective temperature of the blackbody distance : `~astropy.units.Quantity` Distance to the blackbody """ self.irradiance = lambda x: blackbody_lambda(x, T_eff) self.radius = radius self.distance = distance
def generate_planck_blackbody(x, T_eff, frequency=None): # Generates a Planck SED ptype, unit = dimensions_check(T_eff, accepted_dims=[u'temperature']) ptype, unit = dimensions_check(x, accepted_dims=[u'length', u'frequency']) if ptype is None or unit is None: return None if (frequency is None and ptype == u'frequency') or frequency: y = blackbody_nu(x, T_eff) else: y = blackbody_lambda(x, T_eff) return y
def fluxes(self, start=0, wavemax=-1): if (wavemax < 0): wavemax = (const.b_wien / self.kelvin).to( u.AA) # Wien's displacement law else: wavemax = wavemax * u.AA waveset = np.logspace(start, np.log10(wavemax.value + 10 * wavemax.value), num=1000) * u.AA with np.errstate(all='ignore'): flux = blackbody_lambda(waveset, self.kelvin) return waveset, flux
def GrayBody(waves, temperature, bolometric_flux=1*u.erg/(u.cm**2*u.s), wave_0=53*u.micron, beta=-1.5, return_units=u.erg/(u.s*u.cm**2)): eps = (waves/wave_0)**beta # We normalize the returned blackbody so that the integral would be # unity, and we then multiply by the bolometric flux. A normalized # blackbody has f_lam = pi * B_nu / (sigma * T^4), which is what we # calculate here. bb = (np.pi * u.sr * blackbody_lambda(waves, temperature) / const.sigma_sb / temperature ** 4) flambda = bolometric_flux * eps * bb return flambda.to(return_units, u.spectral_density(waves))
def get_instrument_background(self,wvs,solidangle): ''' Returns the instrument background at each wavelength in units of photons/s/Angstrom/arcsecond**2 ''' # TODO: blackbody_lambda is deprecated, change to BlackBody #bb_lam = BlackBody(self.temperature,scale=1.0*u.erg/(u.cm**2*u.AA*u.s*u.sr)) #inst_therm = bb_lam(wvs) inst_therm = blackbody_lambda(wvs, self.temperature) inst_therm *= solidangle inst_therm = inst_therm.to(u.ph/(u.micron * u.s * u.cm**2),equivalencies=u.spectral_density(wvs)) * self.area_ao.to(u.cm**2) inst_therm *= self.get_inst_emissivity(wvs) inst_therm *= self.get_spec_throughput(wvs) return inst_therm
def get_J_CMB(): #returns the mean intensity for the CMB integrated over min_lam to #max_lam (i.e. returns erg/s/cm**2; the same thing as doing 4*sigma #T^4) min_lam = (1.*u.angstrom).to(u.micron) max_lam = (1*u.cm).to(u.micron) wavelengths = np.linspace(min_lam,max_lam,1.e5) flux = blackbody_lambda(wavelengths,cfg.model.TCMB) J = np.trapz(flux,wavelengths).to(u.erg/u.s/u.cm**2/u.sr) solid_angle = 4.*np.pi*u.sr J = J*solid_angle return J
def scale_temperature(self, delta_teff, plot=False): """ Scale up or down the flux according to the ratio of blackbodies between the effective temperature of the IRTF template spectrum and the new effective temperature ``t_eff + delta_teff``. Parameters ---------- delta_teff : float Change in effective temperature to approximate Returns ------- spec : `~libra.IRTFTemplate` Scaled spectral template to ``t_eff + delta_teff`` """ new_t_eff = self.t_eff + delta_teff old_bb = blackbody_lambda(self.wavelength, self.t_eff) new_bb = blackbody_lambda(self.wavelength, new_t_eff) ratio_bbs = (new_bb / old_bb).value if plot: import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(10, 8)) ax.plot(self.wavelength, self.flux, label='init') ax.plot(self.wavelength, old_bb * np.max(self.flux) / np.max(old_bb), label='old bb') ax.plot(self.wavelength, new_bb * np.max(self.flux) / np.max(old_bb), label='new bb', ls='--') ax.plot(self.wavelength, ratio_bbs * self.flux, label='scaled', ls=':') ax.legend() return Spectrum1D(self.wavelength, ratio_bbs * self.flux, header=self.header, t_eff=new_t_eff)
def calibrate(obs, T, kdx=0): sens_raw, wav = obs._calibrate() bb = blackbody_lambda(wav, T) bb /= np.trapz(bb, wav) sens = sens_raw * bb.value sens /= np.median(sens) dw = wav.value[10 + np.argmin(np.gradient(sens[10:-10]))] - wav.value[ 10 + np.argmax(np.gradient(sens[10:-10]))] w_mean = np.mean(wav.value) spec = np.average(obs.data[kdx] / obs.vsr_model[kdx], weights=obs.vsr_model[kdx] / obs.error[kdx], axis=0) spec /= np.median(spec) def func(params, return_model=False): model = np.interp(np.arange(0, obs.data.shape[2]), (wav.value - w_mean) / dw * params[0] + params[1], sens) if return_model: return model return np.sum((spec - model)**2) na = 200 nb = 201 a = np.linspace(100, 150, na) b = np.linspace(40, 100, nb) chi = np.zeros((na, nb)) for idx, a1 in enumerate(a): for jdx, b1 in enumerate(b): chi[idx, jdx] = np.sum( (spec - func([a1, b1], return_model=True))**2) l = np.unravel_index(np.argmin(chi), chi.shape) params = [a[l[0]], b[l[1]]] wavelength = ( (np.arange(obs.data.shape[2]) - params[1]) / params[0]) * dw + w_mean sensitivity = np.interp(np.arange(0, obs.data.shape[2]), (wav.value - w_mean) / dw * params[0] + params[1], sens_raw) wavelength = ( (np.arange(obs.data.shape[2]) - params[1]) / params[0]) * dw + w_mean sensitivity = np.interp(np.arange(0, obs.data.shape[2]), (wav.value - w_mean) / dw * params[0] + params[1], sens_raw) return wavelength, sensitivity
def _calc_bb(self, Tdust, wave, z): lampeak = (b_wien / (Tdust * u.K)).to('Angstrom').value lam1, lam2 = np.array([0.25, 15]) * lampeak if Tdust not in self.Blam: npts = 100 # this hack keeps the points more closely spaced near lampeak dwv1 = np.logspace(np.log10(lam1), np.log10(lampeak), npts) dwv1 = np.cumsum(np.diff(dwv1)) rfwv2 = np.logspace(np.log10(lampeak), np.log10(lam2), npts) rfwave = np.concatenate([(lampeak - dwv1)[::-1], rfwv2]) self.rfwave[Tdust] = rfwave bvals = blackbody_lambda(self.rfwave[Tdust], Tdust).value self.Blam[Tdust] = interp1d(self.rfwave[Tdust], bvals, kind='cubic') Blam = self.Blam[Tdust] i1, i2 = np.searchsorted(wave / (1 + z), [lam1, lam2]) flam = np.zeros_like(wave) flam[i1:i2] = Blam(wave[i1:i2] / (1 + z)) return flam
def inject_example_flare(wavelengths, times, epoch, ind=0): """ Inject example flare. Assume a 10000 K blackbody for flares. Parameters ---------- times : `~numpy.ndarray` Times of observations Returns ------- fluxes : `~numpy.ndarray` Fluxes with flares added. """ halfdur, peakflux = np.loadtxt(trappist_flares_path, unpack=True) total_flux = flare_flux(times, epoch, peakflux[ind] - 1, halfdur[ind]) bb = blackbody_lambda(wavelengths, 10000).value bb_flux_total = np.sum(bb) # total flux from flare in bandpass return bb / bb_flux_total * total_flux[:, np.newaxis]
wavelength3 = spectrum3['wavelength'][:] flux3 = spectrum3['flux'][:] target = SimpleSpectrum(wavelength1, flux1, dispersion_unit=u.Angstrom) source1 = SimpleSpectrum(wavelength2, flux2, dispersion_unit=u.Angstrom) source2 = SimpleSpectrum(wavelength3, flux3, dispersion_unit=u.Angstrom) # Slice the spectra into chunks centered on each TiO band: slicesdlambdas = get_slices_dlambdas(bands, roll_width, target, source1, source2) target_slices, source1_slices, source2_slices, source1_dlambdas, source2_dlambdas = slicesdlambdas time_results = dict() for inds, band in zip(target_slices.wavelength_splits, bands): band_results = dict() R_lambda = (blackbody_lambda(band.core, comp1_temp) / blackbody_lambda(band.core, comp2_temp)).value def random_in_range(min, max): return (max-min)*np.random.rand(1)[0] + min def lnprior(theta): area, f = theta f_S = area * R_lambda net_color = (1 - f_S) * comp1_color + f_S * comp2_color if 0 <= f_S <= 1 and 0 < f: #lnf < 0: return -0.5 * (net_color - target_color)**2/0.05**2 return -np.inf
import pdb import astropy.constants as const import astropy.units as units from astropy.modeling.blackbody import blackbody_lambda, blackbody_nu #Wavelength, kappa, sigma_scattering wks = np.loadtxt('dustkappa_56e-3_pah.inp', skiprows=3) #wks = np.loadtxt('dustkappa_carbon.inp', skiprows=3) #F_lambda wave = wks[:,0] * 1e-6 * units.m kappa = wks[:,1] * (units.cm)**2 / units.g #********** IRS 48 *********** star_surface_F = np.pi * blackbody_lambda(wave, 9000) * (units.rad)**2 wf = np.loadtxt('spectrum_irs.out', skiprows=2) flux_1pc = np.interp(wave.value*1e6, wf[:,0], wf[:,1]) flux_1pc *= units.erg/units.cm**2 flux_1pc *= const.c/wave**2 dust_F1 = star_surface_F * (2*const.R_sun)**2/(13.5*const.au)**2 #!!!This doesn't make sense. Needs to be multiplied by pi dust_F2 = flux_1pc * (const.pc)**2/(13.5*const.au)**2 dust_a = np.trapz(dust_F2*kappa, wave)/const.c rho_d = 1.6 * units.g / (units.cm)**3 gas_accretion_rate = 4e-9 * const.M_sun/units.yr #From Salyk (2013) m_star = 2 * const.M_sun #roughly... r = 13.5 * const.au #a_gr = gas_accretion_rate * (const.G*m_star)**0.5 / (2 * np.pi)**1.5 / rho_d / r**2.5 / dust_a
def test_flare_magnitudes_mixed_with_dummy(self): """ Test that we get the expected magnitudes out """ db = MLT_test_DB(database=self.db_name, driver='sqlite') # load the quiescent SEDs of the objects in our catalog sed_list = SedList(['lte028-5.0+0.5a+0.0.BT-Settl.spec.gz']*4, [17.1, 17.2, 17.3, 17.4], galacticAvList = [2.432, 1.876, 2.654, 2.364], fileDir=getPackageDir('sims_sed_library'), specMap=defaultSpecMap) bp_dict = BandpassDict.loadTotalBandpassesFromFiles() # calculate the quiescent fluxes of the objects in our catalog baseline_fluxes = bp_dict.fluxListForSedList(sed_list) bb_wavelen = np.arange(100.0, 1600.0, 0.1) bb_flambda = blackbody_lambda(bb_wavelen*10.0, 9000.0) # this data is taken from the setUpClass() classmethod above t0_list = [456.2, 41006.2, 117.2, 10456.2] av_list = [2.432, 1.876, 2.654, 2.364] parallax_list = np.array([0.25, 0.15, 0.3, 0.22]) distance_list = 1.0/(206265.0*radiansFromArcsec(0.001*parallax_list)) distance_list *= 3.0857e18 # convert to cm dtype = np.dtype([('id', int), ('u', float), ('g', float)]) photParams = PhotometricParameters() ss = Sed() quiet_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_dummy_quiet_cat.txt') flare_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_dummy_flaring_cat.txt') # loop over several MJDs and verify that, to within a # milli-mag, our flaring model gives us the magnitudes # expected, given the light curves specified in # setUpClass() for mjd in (59580.0, 60000.0, 70000.0, 80000.0): obs = ObservationMetaData(mjd=mjd) quiet_cat = QuiescentCatalog(db, obs_metadata=obs) quiet_cat.write_catalog(quiet_cat_name) flare_cat = FlaringCatalogDummy(db, obs_metadata=obs) flare_cat.scratch_dir = self.scratch_dir flare_cat._mlt_lc_file = self.mlt_lc_name flare_cat.write_catalog(flare_cat_name) quiescent_data = np.genfromtxt(quiet_cat_name, dtype=dtype, delimiter=',') flaring_data = np.genfromtxt(flare_cat_name, dtype=dtype, delimiter=',') self.assertGreater(len(quiescent_data), 2) self.assertEqual(len(quiescent_data), len(flaring_data)) self.assertIn(3, flaring_data['id']) for ix in range(len(flaring_data)): obj_id = flaring_data['id'][ix] self.assertEqual(obj_id, ix) msg = ('failed on object %d; mjd %.2f\n u_quiet %e u_flare %e\n g_quiet %e g_flare %e' % (obj_id, mjd, quiescent_data['u'][obj_id], flaring_data['u'][obj_id], quiescent_data['g'][obj_id], flaring_data['g'][obj_id])) self.assertEqual(quiescent_data['id'][obj_id], flaring_data['id'][obj_id], msg=msg) self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][0]), quiescent_data['u'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][1]), quiescent_data['g'][obj_id], 3, msg=msg) if obj_id != 3: # the models below are as specified in the # setUpClass() method if obj_id == 0 or obj_id == 1: amp = 1.0e42 dt = 3652.5 t_min = flare_cat._survey_start - t0_list[obj_id] tt = mjd - t_min while tt > dt: tt -= dt u_flux = amp*(1.0+np.power(np.sin(tt/100.0), 2)) g_flux = amp*(1.0+np.power(np.cos(tt/100.0), 2)) elif obj_id==2: amp = 2.0e41 dt = 365.25 t_min = flare_cat._survey_start - t0_list[obj_id] tt = mjd - t_min while tt > dt: tt -= dt u_flux = amp*(1.0+np.power(np.sin(tt/50.0), 2)) g_flux = amp*(1.0+np.power(np.cos(tt/50.0), 2)) # calculate the multiplicative effect of dust on a 9000K # black body bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) u_bb_flux = bb_sed.calcFlux(bp_dict['u']) g_bb_flux = bb_sed.calcFlux(bp_dict['g']) a_x, b_x = bb_sed.setupCCM_ab() bb_sed.addDust(a_x, b_x, A_v=av_list[obj_id]) u_bb_dusty_flux = bb_sed.calcFlux(bp_dict['u']) g_bb_dusty_flux = bb_sed.calcFlux(bp_dict['g']) dust_u = u_bb_dusty_flux/u_bb_flux dust_g = g_bb_dusty_flux/g_bb_flux area = 4.0*np.pi*np.power(distance_list[obj_id], 2) tot_u_flux = baseline_fluxes[obj_id][0] + u_flux*dust_u/area tot_g_flux = baseline_fluxes[obj_id][1] + g_flux*dust_g/area self.assertAlmostEqual(ss.magFromFlux(tot_u_flux), flaring_data['u'][obj_id], 3, msg=msg) self.assertAlmostEqual(ss.magFromFlux(tot_g_flux), flaring_data['g'][obj_id], 3, msg=msg) self.assertGreater(np.abs(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id]), 0.001, msg=msg) self.assertGreater(np.abs(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id]), 0.001, msg=msg) else: self.assertAlmostEqual(flaring_data['g'][obj_id], quiescent_data['g'][obj_id]+3*(mjd-59580.0)/10000.0, 3, msg=msg) self.assertAlmostEqual(flaring_data['u'][obj_id], quiescent_data['u'][obj_id]+2*(mjd-59580.0)/10000.0, 3, msg=msg) if os.path.exists(quiet_cat_name): os.unlink(quiet_cat_name) if os.path.exists(flare_cat_name): os.unlink(flare_cat_name)