Beispiel #1
0
    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()
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
    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
Beispiel #8
0
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
Beispiel #9
0
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")
Beispiel #11
0
    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
Beispiel #12
0
    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
Beispiel #13
0
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
Beispiel #15
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
Beispiel #16
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")
Beispiel #18
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
Beispiel #19
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    
Beispiel #20
0
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
Beispiel #21
0
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
Beispiel #22
0
    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
Beispiel #23
0
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
Beispiel #24
0
    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
Beispiel #25
0
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))
Beispiel #26
0
    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
Beispiel #27
0
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
Beispiel #28
0
    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)
Beispiel #29
0
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
Beispiel #30
0
 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
Beispiel #31
0
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]
Beispiel #32
0
        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
Beispiel #33
0
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
Beispiel #34
0
    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)