예제 #1
0
파일: spec.py 프로젝트: janerigby/jrr
def deredden_internal_extinction(sp, this_ebv, colf='rest_fnu', colu="rest_fnu_u", deredden_uncert=True, colwave='rest_wave') :
    # Remove internal extinction as fit by Chisholm's S99 fits.  Assumes Calzetti
    sp_filt = sp.loc[sp[colwave].between(1200,20000)]
    Rv = 4.05  # IS THIS RIGHT FOR STELLAR CONTINUUM?*****
    Av = -1 * Rv * this_ebv  # stupidity w .Series and .as_matrix() is bc extinction package barfs on pandas. pandas->np->pandas
    colfout = colf + "_dered"
    coluout = colu + "_dered"
    sp[colfout]  = pandas.Series(extinction.apply(extinction.calzetti00(sp[colwave].astype('float64').as_matrix(), Av, Rv, unit='aa'), sp[colf].astype('float64').as_matrix()))
    if deredden_uncert :
        sp[coluout]  = pandas.Series(extinction.apply(extinction.calzetti00(sp[colwave].astype('float64').as_matrix(), Av, Rv, unit='aa'), sp[colu].astype('float64').as_matrix()))
    return(0) 
예제 #2
0
    def extinction_curve(self, ws, *params):
        """
		return the reddening curve given wavlengths and params. 
		the type of extinction curve is determined by attribute self.extinction_law. 

		For example, for 'calzetti00' the params are a_v, r_v, and scaling.  
		For example, for 'linear' the params are slope and intercept.  

		Params
		------
		self
		ws (array)
		*params
		"""
        if self.extinction_law == 'linear':
            slope, intercept = params
            return slope * ws + intercept

        elif self.extinction_law == 'calzetti00':
            a_v, r_v, scaling = params
            flux = np.ones(len(ws))
            extlaw = extinction.calzetti00(ws.astype('double'),
                                           a_v=a_v,
                                           r_v=r_v)
            return scaling * extinction.apply(extlaw, flux)
예제 #3
0
    def apply_dust(self):

        import extinction

        for ii in range(self.n_zz):
            if self.dust['flag'] == 'calzetti':
                self.lum_em[:, ii] = extinction.apply(
                    extinction.calzetti00(self.wav_em, self.dust['Av'], 4.05),
                    self.lum_em[:, ii])
            elif self.dust['flag'] == 'cardelli':
                self.lum_em[:, ii] = extinction.apply(
                    extinction.ccm89(self.wav_em, self.dust['Av'], 4.05),
                    self.lum_em[:, ii])
            elif self.dust['flag'] == 'odonnell':
                self.lum_em[:, ii] = extinction.apply(
                    extinction.odonnell94(self.wav_em, self.dust['Av'], 4.05),
                    self.lum_em[:, ii])
            elif self.dust['flag'] == 'fitzpatrick':
                self.lum_em[:, ii] = extinction.apply(
                    extinction.fitzpatrick99(self.wav_em, self.dust['Av'],
                                             3.1), self.lum_em[:, ii])
            elif self.dust['flag'] == 'fitzpatrick07':
                self.lum_em[:, ii] = extinction.apply(
                    extinction.fm07(self.wav_em, self.dust['Av']),
                    self.lum_em[:, ii])
예제 #4
0
def blackbody_spectrum(
    temperature: float,
    scale: float,
    redshift: float = None,
    extinction_av: float = None,
    extinction_rv: float = None,
    get_bolometric_flux: bool = False,
):
    """ """
    wavelengths, frequencies = get_wavelengths_and_frequencies()
    scale_lambda = 1 * FLAM / u.sr
    scale_lambda = 1 / scale * FLAM / u.sr
    scale_nu = 1 / scale * FNU / u.sr

    bb_nu = BlackBody(temperature=temperature * u.K, scale=scale_nu)
    flux_nu = bb_nu(wavelengths) * u.sr
    bolometric_flux = bb_nu.bolometric_flux  #.value

    flux_lambda = flux_nu_to_lambda(flux_nu, wavelengths)

    if extinction_av is not None:
        flux_lambda_reddened = apply(
            calzetti00(np.asarray(wavelengths), extinction_av, extinction_rv),
            np.asarray(flux_lambda),
        )
        flux_nu_reddened = flux_lambda_to_nu(flux_lambda_reddened, wavelengths)
        spectrum_reddened = sncosmo_spectral_v13.Spectrum(
            wave=wavelengths, flux=flux_nu_reddened, unit=FNU)
    spectrum_unreddened = sncosmo_spectral_v13.Spectrum(wave=wavelengths,
                                                        flux=flux_nu,
                                                        unit=FNU)

    if redshift is not None:
        if extinction_av is not None:
            spectrum_reddened.z = 0
            spectrum_reddened_redshifted = spectrum_reddened.redshifted_to(
                redshift,
                cosmo=cosmo,
            )
            outspectrum = spectrum_reddened_redshifted
        else:
            spectrum_unreddened.z = 0
            spectrum_unreddened_redshifted = spectrum_unreddened.redshifted_to(
                redshift, cosmo=cosmo)
            outspectrum = spectrum_unreddened_redshifted

    else:
        if extinction_av is not None:
            outspectrum = spectrum_reddened
        else:
            outspectrum = spectrum_unreddened

    if get_bolometric_flux:
        return outspectrum, bolometric_flux
    else:
        return outspectrum
예제 #5
0
def broken_powerlaw_spectrum(
    alpha1: float,
    scale1: float,
    alpha2: float,
    scale2: float,
    redshift: float = None,
    extinction_av: float = None,
    extinction_rv: float = None,
):
    """ """
    wavelengths, frequencies = get_wavelengths_and_frequencies()

    if scale1 is None:
        flux_nu1 = frequencies.value**alpha1 * u.erg / u.cm**2 / u.s / u.Hz
    else:
        flux_nu1 = (frequencies.value**alpha1 * scale1 *
                    (u.erg / u.cm**2 / u.s / u.Hz))

    if scale2 is None:
        flux_nu2 = frequencies.value**alpha2 * u.erg / u.cm**2 / u.s / u.Hz
    else:
        flux_nu2 = (frequencies.value**alpha2 * scale2 *
                    (u.erg / u.cm**2 / u.s / u.Hz))

    flux_lambda1 = flux_nu_to_lambda(flux_nu1, wavelengths)
    flux_lambda2 = flux_nu_to_lambda(flux_nu2, wavelengths)

    flux_nu = flux_nu1 + flux_nu2
    flux_lambda = flux_lambda1 + flux_lambda2

    spectrum_unreddened = sncosmo_spectral_v13.Spectrum(wave=wavelengths,
                                                        flux=flux_nu,
                                                        unit=FNU)

    if extinction_av is not None:
        flux_lambda_reddened = apply(
            calzetti00(np.asarray(wavelengths), extinction_av, extinction_rv),
            np.asarray(flux_lambda),
        )

        flux_nu_reddened = flux_lambda_to_nu(flux_lambda_reddened, wavelengths)
        spectrum_reddened = sncosmo_spectral_v13.Spectrum(
            wave=wavelengths, flux=flux_nu_reddened, unit=FNU)

    if redshift is not None:
        spectrum_unreddened.z = 0
        spectrum_unreddened_redshifted = spectrum_unreddened.redshifted_to(
            redshift, cosmo=cosmo)
        outspectrum = spectrum_unreddened_redshifted

    else:
        outspectrum = spectrum_unreddened

    return outspectrum
예제 #6
0
파일: test.py 프로젝트: earnric/modules
def test_calzetti00():
    """Test calzetti against another translation of the same base code"""
    
    wave = np.array([2000., 4000., 8000.])
    flux = np.ones(3)

    new_flux = extinction.apply(extinction.calzetti00(wave, -1., 3.1), flux)
    
    # derived using Julia version of IDL calz_unred
    ref_values = np.array([10.5288, 3.88153, 1.61769])

    assert_allclose(new_flux, ref_values, atol=0.0001)
예제 #7
0
파일: test.py 프로젝트: hsalas/extinction
def test_calzetti00():
    """Test calzetti against another translation of the same base code"""

    wave = np.array([2000., 4000., 8000.])
    flux = np.ones(3)

    new_flux = extinction.apply(extinction.calzetti00(wave, -1., 3.1), flux)

    # derived using Julia version of IDL calz_unred
    ref_values = np.array([10.5288, 3.88153, 1.61769])

    assert_allclose(new_flux, ref_values, atol=0.0001)
예제 #8
0
    def add_dust(self):

        for x in self.sed.dtype.names[1:]:
            if self.dust == 'calzetti':
                try:
                    self.sed[x] = apply(
                        calzetti00(self.sed['waves'], self.Av, 4.05),
                        self.sed[x])
                except NameError:
                    self.sed[x] = self.sed[x] * np.exp(
                        -calzetti(self.sed['waves'], self.Av))
            elif self.dust == 'cardelli':
                self.sed[x] = self.sed[x] * np.exp(
                    -cardelli(self.sed['waves'], self.Av))
예제 #9
0
def Calzetti00(Av, wave, Rv=3.1, waveLim=waveLim, QuietMode=True):
    """
    Calculate the extinction that is directly applied to the flux:
        10**(-0.4 * A_lambda).
    For the input wavelength out of the effective range (waveLim), 1 will be
    returned, since this is multiplied on the fluxes.

    Parameters
    ----------
    Av : float
        The Av, V band extinction.
    wave : array
        The wavelength to calculate the extinction, units: micron.
    Rv : float
        Ratio of total to selective extinction, A_V / E(B-V).

    Returns
    -------
    f0 : array
        The ratio of the fluxes after and before the extinction.

    Notes
    -----
    None.
    """
    #-> Check the wavelength coverage.
    fltr = (wave >= waveLim[0]) & (wave <= waveLim[1])
    #-> If the wavelength is fully out of the effective range.
    if np.sum(fltr) == 0:
        if not QuietMode:
            print(
                "Warning (c2000): The input wavelength is out of the effective range!"
            )
        return np.ones_like(wave)
    #-> Calculate the extinction within the effective regime.
    wave_aa = wave[fltr] * 1e4
    av = calzetti00(wave_aa, Av, Rv)
    f0 = np.ones_like(wave)
    f0[fltr] = 10**(-0.4 * av)
    return f0
예제 #10
0
def powerlaw_spectrum(
    alpha: float,
    scale: float,
    redshift: float = None,
    extinction_av: float = None,
    extinction_rv: float = None,
):
    """ """
    wavelengths, frequencies = get_wavelengths_and_frequencies()
    if scale is None:
        flux_nu = frequencies**alpha * u.erg / u.cm**2 / u.s
    else:
        flux_nu = frequencies**alpha * u.erg / u.cm**2 / u.s * scale

    flux_lambda = flux_nu_to_lambda(flux_nu, wavelengths)

    spectrum_unreddened = sncosmo_spectral_v13.Spectrum(wave=wavelengths,
                                                        flux=flux_nu,
                                                        unit=FNU)

    if extinction_av is not None:
        flux_lambda_reddened = apply(
            calzetti00(np.asarray(wavelengths), extinction_av, extinction_rv),
            np.asarray(flux_lambda),
        )

        flux_nu_reddened = flux_lambda_to_nu(flux_lambda_reddened, wavelengths)
        spectrum_reddened = sncosmo_spectral_v13.Spectrum(
            wave=wavelengths, flux=flux_nu_reddened, unit=FNU)

    if redshift is not None:
        spectrum_unreddened.z = 0
        spectrum_unreddened_redshifted = spectrum_unreddened.redshifted_to(
            redshift, cosmo=cosmo)
        outspectrum = spectrum_unreddened_redshifted

    else:
        outspectrum = spectrum_unreddened

    return outspectrum
예제 #11
0
    def extinction(self, Av=1.0, Rv=5.0, applytotemp=True):
        """
        Applies calzetti00 extinction to nuLnu and
        it gives the option for the template
        """
        wave = self.lam * 1e4
        ext = extinction.calzetti00(wave, Av, Rv)

        #Code is giving negative values below 0.001
        #these values are set to 0
        mask = ext < 0.001
        mask = np.array(~mask, dtype=int)
        ext = ext * mask

        self.maxval = np.sum(mask)
        self.ext = ext

        #Applying the extinction directly to nuLnu
        #since it's proportional to Fnu and Flam
        self.nuLnu = self.nuLnu * np.exp(-ext)

        #If we want to apply it to the template
        if applytotemp:
            self.template = self.template * np.exp(-ext)
예제 #12
0
def extinct(ls,
            EBV=0.1,
            HyperZ=True,
            type='calzetti',
            atmos=False,
            tatmos='eso',
            unit='aa'):
    """
  http://extinction.readthedocs.io/en/latest/                                                                                                             
  https://github.com/kbarbary/extinction/blob/19be03f7e04ce22802c52137205aa67ae7a0a8de/extinction.pyx

  ls: wavelength in angstroms; alternative unit of 'invum' (inverse microns).                                                                           
  A_V: extinction in magnitudes at characteristic V band.                                                                                               
  Ratio of total to selective extinction, Rv = A_V / E(B - V).                                                                                         
  
  -- https://arxiv.org/pdf/1209.2152.pdf                                                                                                             
  -- https://arxiv.org/pdf/astro-ph/9911459.pdf                                                                                                      
  
  Both studies used template spectra including dust attenuation following the Calzetti law.                                                              
  Finkelstein et al. inferred an attenuation at 1500A, A1500, of 1.3 magnitudes at z=4                                                                
  and A1500 < 0.25 at z=7. In contrast, for galaxies with z = 6.5, McLure et al. found A1500=0.4,                                                     
  a value above the upper limit found by Finkelstein et al. In many observational studies the dust                                                     
  attenuation is inferred from the UV continuum slope estimated from a single colour. Bouwens et al. (2011)                                          
  measured an average UV continuum slope of -3 for galaxies at z = 7. However, this value was measured to be -2.2                                      
  when more data were collected by the HST WFC3 (Bouwens et al. 2012). This illustrates how the scarcity of high                                       
  redshift data can bias the estimation of dust attenuation.                                                                                         
      
  UV continuum slope is a poor indicator of dust attenuation, as our results are extremely sensitive to the choice                                      
  of extinction curve used as the input to the attenuation of starlight calculations. For our standard choice, a Milky Way (MW)                          
  extinction curve, galaxies get bluer when they are attenuated, which, as we explain in Section 6 is due to the presence of a                          
  bump in the extinction curve.                                                                                                             
  Usually the term dust 'extinction' refers to the attenuation of the light from a point source placed behind a screen of dust.                          
  Thus, the 'extinction' is independent of the geometry of the system.                                                                                    

  With a_\lambda = L_\lambda (attenuated) /L_\lambda (unattenuated), t_eff (\lambda) = -ln(a_\lambda).                                                   
  Magnitudes: \tau_\eff = A_\lambda / (2.5 \log_10 e).                                                                                                  
  
  MW extinction: Cardelli, Clayton & Mathis (1989) with A_V = 1.0 (Amplitude) and R_V = 3.1 (Shape).                                                     
  """

    ## Av = Rv * E(B-V); Rv = 4.05
    if HyperZ == False:
        if type == 'odonnell':
            ## MW extinction O'Donnell (1994)
            Rv = 3.1
            ext = extinction.odonnell94(ls, Rv * EBV, Rv)

        elif type == 'fitzpatrick':
            ## LMC extinction; Fitzpatrick (1999)
            Rv = 3.10
            ext = extinction.fitzpatrick99(ls, Rv * EBV, Rv)

        else:
            Rv = 4.05
            ext = extinction.calzetti00(
                ls, Rv * EBV,
                Rv)  ## Extinction in magnitudes at each input wavelength.

    else:
        """
    http://webast.ast.obs-mip.fr/hyperz/hyperz_manual1/node10.html                                                                                      
    The extinction curve are expressed in  k(lambda[A]) vs lambda[A].                                                                                   
    Apply a E(B-V) correction by:                                                                                                                            
    flux_attenuated = flux_intrinsic * 10^[-0.4*k(l)*Av/Rv] 
    """

        files = {
            'fitzpatrick': 'LMC_Fitzpatrick.dat',
            'allen': 'MW_Allen.dat',
            'seaton': 'MW_seaton.dat',
            'prevot': 'SMC_prevot.dat',
            'calzetti': 'SB_calzetti.dat'
        }
        Rvs = {
            'fitzpatrick': 3.10,
            'allen': 3.10,
            'seaton': 3.10,
            'prevot': 2.72,
            'calzetti': 4.05
        }

        files[
            'calzetti_mod'] = 'SB_calzetti_mod.dat'  ## modified Calzetti law including contribution from 2175A bump (Massaroti et al., 2001)
        Rvs['calzetti_mod'] = 4.05

        data = np.loadtxt('ext-laws/' + files[type])
        extinterp = interp1d(data[:, 0],
                             EBV * data[:, 1],
                             kind='cubic',
                             bounds_error=False,
                             fill_value=0.0)
        ext = extinterp(ls)

    if atmos == True:
        files = {
            'eso': 'extinc_eso.dat',
            'ctio': 'extinc_ctio.dat'
        }  ## Atmospheric extinction curves
        Rv = 3.1

        data = np.loadtxt('ext-laws/' + files[tatmos])
        extinterp = interp1d(data[:, 0],
                             EBV * data[:, 1],
                             kind='cubic',
                             bounds_error=False,
                             fill_value=0.0)

        ext += extinterp(ls)

    return 10.**(
        -0.4 * ext
    )  ## Deredden with -Av; Positive extinction values decrease flux.
예제 #13
0
    wave_aa = wave[fltr] * 1e4
    av = calzetti00(wave_aa, Av, Rv)
    f0 = np.ones_like(wave)
    f0[fltr] = 10**(-0.4 * av)
    return f0


if __name__ == "__main__":
    import extinction
    import matplotlib.pyplot as plt

    Rv = 3.1
    wave = np.logspace(np.log10(910.), np.log10(30000.), 2000)
    a_lambda = {
        'ccm89': extinction.ccm89(wave, 1.0, Rv),
        'odonnell94': extinction.odonnell94(wave, 1.0, Rv),
        'fitzpatrick99': extinction.fitzpatrick99(wave, 1.0),
        "c00": extinction.calzetti00(wave, 1.0, Rv),
        'fm07': extinction.fm07(wave, 1.0)
    }
    for mn in a_lambda.keys():
        ext = a_lambda[mn]
        plt.plot(wave, ext, label=mn)
    c00_2 = -2.5 * np.log10(Calzetti00(2., wave / 1e4, Rv))
    c00_3 = extinction.calzetti00(wave, 2.0, Rv)
    plt.plot(wave, c00_2, color="turquoise")
    plt.plot(wave, c00_3, color="tomato", linestyle=":")
    plt.xscale("log")
    plt.legend(loc="upper right")
    plt.show()
예제 #14
0
def make_a_stack(labels, rootname, norm_region, norm_func, norm_method_text, mage_mode, zchoice, deredden=False, EBV=[], deredden_MW=False, colcont="fnu_cont") :
    # Note: this is stacking in the rest-frame.  
    plt.close('all')
    plt.ion()
    plt.figure(figsize=(20,5))
#    specs = jrr.mage.getlist_labels(mage_mode, labels)
    specs = jrr.mage.wrap_getlist(mage_mode, which_list="labels", labels=labels)
    Nspectra = len(specs)
    print("DEBUG, Nspectra is", Nspectra)
    stacklo =  800. #A      # Create a rest-frame wavelength array to stack into
    stackhi = 3000. #A
    disp = 0.1 # Angstroms  # observed-frame wavelength binning is ~0.3A pper pix for RCS0327.  So, want ~0.1A in rest-frame
    nbins = int((stackhi - stacklo)/disp)
    wave_stack    = np.linspace(stacklo, stackhi, num=nbins)
    nfnu_stack    = np.ma.zeros(shape=(Nspectra, nbins))   # create array that will hold all the spectra
    nfnu_u_stack  = np.ma.zeros(shape=(Nspectra, nbins))

    print("Filename    label      N_pixels     rest-frame wavelength range (A)")
    for ii in range(0, Nspectra) :                  #nfnu_stack[ii] will be ii spectrum
        label     = specs['short_label'][ii]
        filename  = specs['filename'][ii]

        if(zchoice == "stars") :     # Update 8/2016, enabling either method to to set systemic redshift, selectable as zchoice
            zz =  specs['z_syst'][ii] # using john chisholm's S99 fits to photospheric absorption lines where possible.
        elif(zchoice == "neb") :
            zz =  specs['z_neb'][ii]  # what I used prior to 21 july 2016.
        else : raise ValueError('Error, I do not recognize input zchoice (choice to set systemic redshift) as stars or neb')
        # OLD (sp, resoln, dresoln)  = jrr.mage.open_spectrum(filename, zz, mage_mode)
        (sp, resoln, dresoln, LL, zz_syst) = jrr.mage.wrap_open_spectrum(label, mage_mode, addS99=True)
         
        # set uncertainties high near skylines [O I] 5577\AA\ and [O I]~6300\AA,
        skyline = (5577., 6300.)
        skywidth = 10.0  # flag spectrum +- skywidth of the skyline
        sp.fnu_u[sp['wave'].between(skyline[0]-skywidth, skyline[0]+skywidth)] = 1.0 # huge uncert near skylines
        sp.fnu_u[sp['wave'].between(skyline[1]-skywidth, skyline[1]+skywidth)] = 1.0 # huge uncert near skylines
        sp.fnu_u[sp[colcont].eq(9999)] = 1.0  # Set huge uncertainties where continuum undefined

        # Mask out known intervening absorbers
        vmask = 200. # +-200km/s
        LL['vmask'] = vmask
        jrr.spec.flag_near_lines(sp, LL, linetype=('INTERVE',))
        sp.fnu_u[sp['linemask']] = 1. # Set huge uncertainties at positions of known intervening absorbers
        if deredden_MW :
            print("DEBUGGING, dereddening Milky Way extinction")
            Rv = 3.1
            Av = -1 * Rv *  specs['EBV_MW'][ii]  # Want to deredden, so negative sign
            sp.fnu   = pandas.Series(extinction.apply(extinction.ccm89(sp.wave.as_matrix(), Av, Rv), sp.fnu.as_matrix()))
            sp.fnu_u = pandas.Series(extinction.apply(extinction.ccm89(sp.wave.as_matrix(), Av, Rv), sp.fnu_u.as_matrix()))
            sp[colcont] = pandas.Series(extinction.apply(extinction.ccm89(sp.wave.as_matrix(), Av, Rv), sp[colcont].as_matrix()))
            sp['fnu_cont_u'] = pandas.Series(extinction.apply(extinction.ccm89(sp.wave.as_matrix(), Av, Rv), sp['fnu_cont_u'].as_matrix()))
            
        (rest_wave, rest_fnu, rest_fnu_u) = jrr.spec.convert2restframe(sp.wave, sp.fnu,  sp.fnu_u,  zz, 'fnu')
        (junk   , rest_cont, rest_cont_u) = jrr.spec.convert2restframe(sp.wave, sp[colcont], sp.fnu_cont_u, zz, 'fnu')
        # should now have arrays of rest wavelength, fnubda, and continuum, as
        # rest_wave, rest_fnu, rest_fnu_u, rest_cont, rest_cont_u
        print(filename, label, len(rest_wave), end=' ')
        print("  %.2f  %.2f" % (  rest_wave[0], rest_wave[-1:]))

        if deredden and len(EBV) :
            this_ebv =  S99.loc[label,  'E(B-V)']
            Rv = 4.05
            Av = -1 * Rv * this_ebv  # stupidity w .Series and .as_matrix() is bc extinction package barfs on pandas. pandas->np->pandas
            rest_fnu    = pandas.Series(extinction.apply(extinction.calzetti00(rest_wave.as_matrix(), Av, Rv), rest_fnu.as_matrix()))
            rest_fnu_u  = pandas.Series(extinction.apply(extinction.calzetti00(rest_wave.as_matrix(), Av, Rv), rest_fnu_u.as_matrix()))
            rest_cont   = pandas.Series(extinction.apply(extinction.calzetti00(rest_wave.as_matrix(), Av, Rv), rest_cont.as_matrix()))
            rest_cont_u = pandas.Series(extinction.apply(extinction.calzetti00(rest_wave.as_matrix(), Av, Rv), rest_cont_u.as_matrix()))            
        
        # Normalize the spectrum and error spectrum
        (temp_norm_fnu, temp_sig) = norm_func(rest_wave, rest_fnu, rest_fnu_u, rest_cont, rest_cont_u, norm_region)
        nfnu_stack[ii]   = np.ma.masked_invalid(jrr.spec.rebin_spec_new(rest_wave, temp_norm_fnu,   wave_stack))# normalized fnu, rebinned
        nfnu_u_stack[ii] = np.ma.masked_invalid(jrr.spec.rebin_spec_new(rest_wave, temp_sig, wave_stack)) # uncertainty on above
        plt.step(wave_stack, nfnu_stack[ii])

    # fnu_u_stack is 1sigma uncertainty spectrum.  weight is 1/sigma**2
    nfnu_u_stack += 0.00001            # add a very small number to avoid 1/zero errror
    weight_stack = nfnu_u_stack**-2
    sig2clip = 2  # clip at N sigma,  in astropy.stats.sigma_clip
    # Use a masked average to deal with the whole wavelength range.  numpy.ma is masking
    mask1 = np.isnan(nfnu_stack)    # interp1d writes NaNs in non-overlap region.  Mask these
    mask2 = np.isnan(nfnu_u_stack)  # ditto for uncertainty
    crazy_high = 1000.
    mask3 = np.greater(nfnu_stack, crazy_high) + np.less(nfnu_stack, -1*crazy_high)  # flag crazy flux values.
    mask = mask1 + mask2 + mask3
    print("DEBUGGING masks", mask1.sum(), mask2.sum(), mask3.sum(), mask.sum(), mask.shape)
    nfnu_clip  = sigma_clip(nfnu_stack, sig=sig2clip, iters=None, axis=0)   ## Sigma clipping
    X_avg,     sumweight1   = np.ma.average(nfnu_stack, axis=0, weights=weight_stack, returned=True) # weighted avg of continuum-normalized spectra
    X_clipavg, sumweight2   = np.ma.average(nfnu_clip,  axis=0, weights=weight_stack, returned=True) # weighted avg of cont-normalized spectra, w sig clip
    X_Ngal = np.sum((1 - mask), axis=0)        # Number of galaxies that went into the stack at that wavelength
    X_sigma     = sumweight1**-0.5
    X_clipsigma = sumweight2**-0.5  # spiky, dunno why.  Presumably legacy of sigma_clip?  Don't use it
    X_median = np.ma.median(nfnu_stack, axis=0)

    plt.step(wave_stack, X_avg, color="black", linewidth=3)
    plt.ylim( -1, 3)
    plt.xlim(1000, 1200)
    plt.draw()
    plt.show()
    #pdb.set_trace()
    if GOSLOW :   plt.pause(4)

    # Jack-knife: drop one spectrum and make weighted average, repeat.  Measure the stdev.
    jackknife = np.ma.zeros(shape=(Nspectra, nbins))
    jack_var  = np.ma.zeros(shape=nbins)
    for ii in range(0, Nspectra) :
        jnf = nfnu_stack.copy()
        print("Jackknife, dropping ", specs['short_label'][ii], " from the stack")
        jnf[ii, :].mask = True  # Mask one spectrum
        jackknife[ii], weight = np.ma.average(jnf, axis=0, weights=weight_stack, returned=True)  # all the work is done here.
        jack_var = jack_var +  (jackknife[ii] - X_avg)**2
    jack_var *= ((Nspectra -1.0)/float(Nspectra))   
    X_jack_std = np.sqrt(jack_var)
    # Jackknife variance estimation, from wikipedia: var = (n-1)/n * sum(i=1 to n) of (xi  - x.)**2

    #Output the stacked spectrum
    long_rootname = "magestack_by" + zchoice + "_" + rootname
    head  = '# Stack(s) of the MagE spectral atlas of lensed galaxies, named   ' + long_rootname + '\n'
    head += '# Generated on ' + time.strftime("%d/%m/%Y") + '(dd/mm/yyr)\n'
    head += '# Generated from ' + str(labels) + "\n"
    head += '# ' + norm_method_text + "\n"
    head += '# Columns are: \n'
    head += '# wave    :   Rest-frame vacuum wavelength, in Angstroms.  Covers ' + str(stacklo) + " to " + str(stackhi) + '\n'
    head += '# X_avg   :   Weighted avg of continuum-normalized fnu spectra.\n'
    head += '# X_clipavg: same as X_avg, but weighted avg done with sigma clipping at sigma=' + str(sig2clip) + '\n'
    head += '# X_median:  median of continuum-normalized fnu spectra.  No weighting.\n'
    head += '# X_sigma :  uncertainty on X_avg and X_clipavg, from propagating individual error spectra\n'
    head += '# X_jack_std : sqrt of variance estimate from jackknife test. \n'
    head += '# Ngal    :  Number of galaxies that went into the stack at that wavelength.\n'
    head += 'restwave    X_avg    X_clipavg  X_median  X_sigma   X_jack_std   Ngal'
    outfile = long_rootname + "_spectrum.txt"
    np.savetxt(outfile, np.transpose([wave_stack, X_avg, X_clipavg, X_median, X_sigma, X_jack_std,  X_Ngal]), "%.3f  %.2E  %.2E  %.2E  %.2E %.2E  %d", header=head, comments="")
    maskout_head = "#This mask shows which galaxies were stacked at each wavelength. 0=gal used.  1=gal masked out.\n"
    outfile = long_rootname + "_maskused.txt"
    jack_head = "restwave   " + re.sub("\n", "", str(specs.short_label.values))
    jack_head = re.sub("'", "", jack_head)
    jack_head = re.sub("\[", "", jack_head)
    jack_head = re.sub("\]", "", jack_head)
    maskout_head += jack_head
    format_string = "%.3f " + "%.0f " * mask.shape[0]
    np.savetxt(outfile, np.transpose(np.vstack((wave_stack, mask))), fmt=format_string, header=maskout_head, comments="")  # so much pain to figure out this syntax
    # The above np magic allows us to concatenate wave_stack (which is 1D, and mask, which is 2D, and the 2nd dimension isn't defined. painful"

    # output the jackknife stacks
    outfile = long_rootname + "_jackknife.txt"
    head2 =  "# Weighted-averages of MagE spectra, each missing 1 spectrum, for jackknife tests\n#wave(A)   weighted_means_w_jackknife\n"
    head2 += "# Each jackknife is missing the following spectrum:\n" + jack_head
    np.savetxt(outfile, np.transpose(np.vstack((wave_stack, jackknife))), fmt="%.5E", header=head2, comments="")

    # plot the stacked spectrum
    plt.clf()
    plt.step(wave_stack, X_avg, color="black")
    plt.step(wave_stack, X_median, color="blue")
    plt.step(wave_stack, X_sigma, color="orange")
    plt.step(wave_stack, X_jack_std, color="red")
    plt.ylabel(r'$f_\nu$')
    #plt.xlim(stacklo, stackhi)
    plt.xlim(800,3000)
    plt.ylim(-1,2)
    figname = long_rootname + "_quicklook.pdf"
    plt.savefig(figname)
    plt.show()
    if GOSLOW :   plt.pause(4)


    PLOT_NGAL = True
    if PLOT_NGAL :
        plt.clf()
        plt.xlabel(r'wavelength ($\AA$)')
        plt.ylabel("number of galaxies that went into the stack")
        plt.plot(wave_stack, X_Ngal, color="red")
        plt.ylim(0,16)
        figname = long_rootname + "_Ngals_in_stack.pdf"
        plt.savefig(figname)
        plt.show()
    #raise Exception("I need to see whats happening")
    return(wave_stack, nfnu_stack, nfnu_u_stack)
예제 #15
0
def BC03_maker(ngal=None, restframe=False, printit=False, test=False, seed=314, redshifts=None, magnitudes=None, alliseds=False,\
               calzetti=False, madau=False, hiwave=1.e4):

    np.random.seed(seed)

    if type(redshifts) == type(None):
        redshifts = 1.5 + np.linspace(0., 4.0, 20)

    if type(magnitudes) == type(None):
        magnitudes = 20.0 + np.arange(0., 7.0, 0.1)

    if printit:
        print('\n\nSolving for redshifts:\n' + ''.join('%.3lf, ' % x
                                                       for x in redshifts))
        print('\n\nSolving for magnitudes:\n' + ''.join('%.3lf, ' % x
                                                        for x in magnitudes))

    filters = prep_filters()

    dbands = ['u', 'g', 'r', 'i', 'z', 'y', 'J']
    dfilters = OrderedDict(zip(dbands, [filters[x] for x in dbands]))

    owave = np.arange(3.6e3, hiwave, 0.1)  ##  Matched to gal. maker.
    count = 0

    flux = []

    ##  Meta.
    objtypes = []
    subtypes = []
    meta_zs = []
    meta_dbands = []
    meta_ages = []
    meta_imfs = []
    meta_taus = []
    meta_metals = []
    meta_mags = []
    meta_calz = []

    root = os.environ['BEAST'] + '/gal_maker/dat/BC03/salpeter/'
    spectra = []

    ##  Save metallicity, tau and ages for every retained template.
    Ms = []
    Is = []
    Ts = []
    Ages = []

    files = []

    if alliseds:
        files = glob.glob(os.environ['BEAST'] + '/gal_maker/dat/BOWLER/ised/*')

    else:
        ##  Single stellar population.
        for metallicity in ['m42', 'm62']:
            files.append(root + '/bc2003_hr_%s_salp_ssp.ised' % metallicity)

    for fname in files:
        ##  SED ordered by increasing frequency [ergs/s/Hz], Age [GYr], (Monotonically increasing) vs [Hertz]; (Monotonically decreasing) Waves [AA].
        seds, ages, vs, ls = read_ised(fname)

        if alliseds:
            metallicity, imf, dummy, xx, xxx = fname.split(
                'bc2003_lr_')[1].split('.ised')[0].split('_')
            tau = np.float(xx + '.' + xxx)

        else:
            metallicity = fname.split('_')[3]
            imf = 'salp'
            tau = np.NaN

        for ii, sed in enumerate(seds.T):
            if (ages[ii] > 0.01) & (ii % 25 == 0):
                ##  Sample of Ages and metallicities.
                ##  vs * Fv = ls * Fl.  Fig. 13.5 of Cosmological Physics.

                if metallicity == 'm42':
                    Ms.append(0.5)  ##  Zo

                elif metallicity == 'm62':
                    Ms.append(1.0)  ##  Zo

                else:
                    raise UserWarning(
                        'Hard code metallicity for given BC03 mXX: %s' %
                        metallicity)

                Is.append(imf)
                Ts.append(tau)
                Ages.append(ages[ii])
                spectra.append(sed)

    nmax = len(redshifts) * len(spectra) * len(magnitudes)

    if (ngal is None):
        ngal = nmax

    elif (ngal > nmax):
        ngal = nmax

        raise ValueWarning(
            'Requested LBG number is larger than that available.')

    else:
        pass

    runs = [[z, specid, mag] for mag in magnitudes for z in redshifts
            for specid in np.arange(len(spectra))]

    if test:
        runs = [[2.3, 0, 22.], [2.3, 1, 22.], [1.7, 2, 22.], [1.7, 3, 22.],
                [2.2, 4, 22.]]
        printit = True
        ngal = 5

    if restframe:
        ngal = len(spectra)
        runs = [[0.0, specid, 23.5] for specid in np.arange(len(spectra))]
        printit = True

        print(runs)

    ##  nmax random selection of galaxies.
    runs = np.array(runs)
    runs = runs[np.random.choice(runs.shape[0], ngal, replace=False)]

    ##  flux_factors = 10.0 ** (0.4 * (magnitudes[0] - magnitudes))
    for run in runs:
        redshift = np.float(run[0])
        specid = np.rint(run[1]).astype(np.int)
        magnitude = np.float(run[2])

        EBV = 0.1 * choice(5, 1, replace=True)

        if printit:
            print('\nSolving for redshift: %.3lf, mag: %.3lf, spec. Age: %s, Spec. Metallicity: %s, EBV: %.3lf' % (redshift, magnitude,\
                                                                                                                   str(Ages[specid]), Ms[specid],\
                                                                                                                   EBV))

        ##  Spectra wavelength is very large.  Cut to 2.e4 AA.
        waves = ls[ls < 2.e4]
        Fv = spectra[specid][ls < 2.e4]

        if calzetti:
            Av = 4.05 * EBV

            waves = waves.astype(np.double)
            Fv = ext_apply(calzetti00(waves, a_v=Av, r_v=4.05, unit='aa'), Fv)

        if madau & (not restframe):
            Fv = lephare_madau(waves[::-1], redshift)[::-1] * Fv

        waves = waves * u.AA
        Fv = Fv * u.erg / u.s / u.cm / u.cm / u.Hz

        Fl = Fv.to(u.erg / u.s / u.cm / u.cm / u.AA,
                   equivalencies=u.spectral_density(waves))

        ##  Change wavelength sampling to linear with dlambda = 0.1A.
        xx = np.arange(waves.value.min(), waves.value.max(), 0.1)

        ##  Note:  reverse to monotically increasing wavelength for resample_flux.
        Fl = resample_flux(xx, waves.value[::-1],
                           Fl.value[::-1]) * u.erg / u.s / u.cm / u.cm / u.AA
        waves = xx * u.AA

        Fv = Fl.to(u.erg / u.s / u.cm / u.cm / u.Hz,
                   equivalencies=u.spectral_density(waves))
        vs = waves.to(u.Hz, equivalencies=u.spectral())

        if not restframe:
            ## Redshift spectra for quickspectra input.  'Else', leave unredshifted for redrock template.
            vs, Fv = redshift_spectra(vs.value, Fv.value, redshift)

            vs = vs * u.Hz
            waves = vs.to(
                u.AA, equivalencies=u.spectral())  ##  Redshifted wavelength.

            Fv = Fv * u.erg / u.s / u.cm / u.cm / u.Hz

        mags = get_appmags(vs.value[::-1],
                           Fv.value[::-1],
                           filters,
                           printit=printit)

        dband = get_detband(redshift,
                            dfilters,
                            printit=False,
                            restframe=restframe)
        Fv *= 10.**(0.4 * (mags[dband] - magnitude)
                    )  ##  Normalise to magnitudes[0], e.g. 20.0 in g.

        ##  And check.
        ##  mags  = get_appmags(vs, Fv, filters, printit = True)

        ##  F_lambda from F_nu.
        Fl = Fv.to(u.erg / u.s / u.cm / u.cm / u.AA,
                   equivalencies=u.spectral_density(
                       waves))  ##  [       ergs / s / sq. cm / A]

        if restframe:
            wave = waves.value
            Fl /= 1.e-17

            owave = xx

        else:
            Fl /= 1.e-17  ##  [1.e-17 ergs / s / sq. cm / A]

            assert np.all(np.diff(owave) > 0.0)

            Fl = resample_flux(owave, waves.value,
                               Fl.value) * u.erg / u.s / u.cm / u.cm / u.AA

        ##  Magnitude is arbitrary for redrock template.
        objtypes.append('BC03')

        if alliseds:
            subtypes.append('ALL')

        else:
            subtypes.append('SSP')

        meta_zs.append(redshift)
        meta_dbands.append(dband)
        meta_mags.append(magnitude)
        meta_ages.append(Ages[specid])
        meta_metals.append(Ms[specid])
        meta_imfs.append(Is[specid])
        meta_taus.append(Ts[specid])
        meta_calz.append(EBV[0])

        flux.append(Fl.value)

        count += 1

        if count >= ngal:
            flux = tuple(flux)
            flux = np.column_stack(flux)
            flux = flux.T

            meta =  Table([objtypes, subtypes, meta_zs, meta_ages, meta_metals, meta_imfs, meta_taus, meta_calz, meta_dbands, meta_mags],\
                           names=('OBJTYPE', 'SUBTYPE', 'REDSHIFT', 'AGE', 'METALLICITY', 'IMF', 'Tau', 'CalzEBV', 'dband', 'AB mag'),\
                            meta={'name': 'BC03 MAKER META'})

            if flux.min() < 0.0:
                raise ValueError('ERROR:  z: %.3lf, spectra: %s' %
                                 (redshift, specname))

            return flux, owave, meta
예제 #16
0
def test_sdss_halpha(fname,
                     fluxkey,
                     magkey,
                     magerrprefix,
                     bands,
                     scatter_density=True,
                     zkey="z",
                     xmin=-17,
                     xmax=-13,
                     output=None,
                     bands_ebv=None,
                     wline=6562.8 * u.AA):
    bands_ebv = ["G", "I"] if bands_ebv is None else bands_ebv
    ############################################################################
    # Reading transmission curves for S-PLUS
    filters_dir = os.path.join(os.getcwd(), "filter_curves-master")
    filenames = sorted([os.path.join(filters_dir, _) for _ in os.listdir( \
                        filters_dir)])
    filternames = [os.path.split(_)[1].replace(".dat", "") for _ in filenames]
    filternames = [
        _.replace("F0", "F").replace("JAVA", "") for _ in filternames
    ]
    filternames = [_.replace("SDSS", "").upper() for _ in filternames]
    fcurves = [np.loadtxt(f) for f in filenames]
    wcurves = [curve[:, 0] * u.AA for curve in fcurves]
    trans = [curve[:, 1] for curve in fcurves]
    wcurves = dict(zip(filternames, wcurves))
    trans = dict(zip(filternames, trans))
    halpha = EmLine3Filters(wline, [_.upper() for _ in bands], wcurves, trans)
    ############################################################################
    # Reading catalog and remove objects out of z-range
    wdir = os.path.join(context.home_dir, "catalogs")
    filename = os.path.join(wdir, fname)
    table = Table.read(filename)
    if zkey in table.colnames:
        table = table[table[zkey] < 0.02]
    ############################################################################
    # Cleaning table against large errors in mgnitudes
    magerrs = np.array([
        table["{}{}{}".format(magerrprefix, band, magkey)].data
        for band in bands
    ])
    idx = np.where(np.nanmax(magerrs, axis=0) < 0.2)[0]
    table = table[idx]
    ############################################################################
    # Estimating the extinction
    gi = np.array(
        [table["{}{}".format(band, magkey)].data for band in bands_ebv])
    g_i = gi[0] - gi[1]
    ebvs = np.clip(0.206 * np.power(g_i, 1.68) - 0.0457, 0, np.infty)
    Rv = 4.1
    Avs = Rv * ebvs
    corr = np.array([
        extinction.remove(
            extinction.calzetti00(np.atleast_1d(wline), Av, Rv)[0], 1)
        for Av in Avs
    ])
    ############################################################################
    # Correcting observations for Galactic extinction
    coords = SkyCoord(table["ra"] * u.degree, table["dec"] * u.degree)
    sfd = SFDQuery()
    ebv_mw = sfd(coords)
    Rv_mw = 3.1
    Av_mw = Rv_mw * ebv_mw
    corr_mw = np.array([
        extinction.remove(
            extinction.ccm89(halpha.wpiv, Av, Rv_mw)[0], np.ones(3))
        for Av in Av_mw
    ]).T
    ############################################################################
    # Calculating H-alpha
    mags = np.array(
        [table["{}{}".format(band, magkey)].data for band in bands])
    flam = mag2flux(mags, halpha.wpiv) * corr_mw
    flux_halpha_nii = halpha.flux_3F(flam)
    log_halpha = np.where(g_i <= 0.5,
                          0.989 * np.log10(flux_halpha_nii.value) - 0.193,
                          0.954 * np.log10(flux_halpha_nii.value) - 0.753)
    halpha_sdss = np.log10((table[fluxkey]) * np.power(10., -17))
    halpha_splus = log_halpha + np.log10(corr)
    ############################################################################
    # Selecting only regions within limits of flux
    idx = np.where(
        np.isfinite(halpha_sdss * halpha_splus) & (halpha_sdss > xmin)
        & (halpha_splus < xmax))
    halpha_sdss = halpha_sdss[idx]
    halpha_splus = halpha_splus[idx]
    ############################################################################
    fig = plt.figure()
    if scatter_density:
        ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
        density = ax.scatter_density(halpha_sdss, halpha_splus, cmap="magma_r")
        fig.colorbar(density, label='Number of points per pixel')

    else:
        ax = fig.add_subplot(1, 1, 1)
        label = "mag_key={}".format(magkey)
        counts, xedges, yedges, im = ax.hist2d(halpha_sdss,
                                               halpha_splus,
                                               bins=(50, 50),
                                               cmap="bone_r")
        plt.legend(title=label)
        fig.colorbar(im, ax=ax)
    ax.set_aspect("equal")
    plt.xlim(xmin, xmax)
    plt.ylim(xmin, xmax)
    plt.plot(np.linspace(xmin, xmax, 100), np.linspace(xmin, xmax, 100), "--r")
    plt.xlabel(r"$\log$ H$\alpha$ (erg / s / cm$^2$) -- SDSS")
    plt.ylabel(r"$\log$ H$\alpha$ (erg / s / cm$^2$) -- SPLUS")
    axins = inset_axes(ax,
                       width="80%",
                       height="80%",
                       bbox_to_anchor=(.65, .05, .38, .38),
                       bbox_transform=ax.transAxes,
                       loc=3)
    diff = halpha_splus - halpha_sdss
    median = np.nanmedian(diff)
    std = np.nanstd(diff)
    title = "med: {:.2f} std: {:.2f}".format(median, std)
    axins.hist(diff, bins=20)
    axins.set_title(title)
    plt.tight_layout()
    if "output" is not None:
        plt.savefig(
            output,
            dpi=250,
        )
    plt.show()
예제 #17
0
                             seed=314,
                             redshifts=None,
                             magnitudes=None,
                             hiwave=2.e4)

filters = prep_filters(['LSST', 'VIDEO'], normed=True)

for i, band in enumerate(list(filters.keys())):
    pl.fill_between(filters[band]['ls'] / 1.e4,
                    2. * filters[band]['Ts'],
                    alpha=0.4,
                    label='')  ##  label=filters[band]['ppkey']

for i, x in enumerate(flux):
    rwave = wave / (1. + meta['REDSHIFT'][i])
    x = ext_apply(calzetti00(rwave, a_v=0.2, r_v=4.05, unit='aa'), x)

    ##  Madau extinction.
    x *= lephare_madau(rwave, meta['REDSHIFT'][i])

    pl.semilogy(wave / 1.e4,
                x,
                label=r'$%+ .1lf\AA, z=%.1lf$' %
                (meta['Lya-EW'][i], meta['REDSHIFT'][i]))

pl.xlabel(r'$\lambda \ [\mu m]$')
pl.ylabel(r'$F_\lambda \ [10^{-17} \ \rm{ergs} / s / \rm{cm}^2 / \AA]$')

pl.xlim(0.3, 1.9)
pl.ylim(0.1, 30.1)
예제 #18
0
def deredden(wave,
             flux,
             ra,
             dec,
             scaling=0.86,
             reddening_law='fitzpatrick99',
             dustmaps_dir=None,
             r_v=3.1,
             ebv=None):
    """Dereddens the given spectrum, given a right ascension and declination or :math:`E(B-V)`.

    Parameters
    ----------
    wave : array
        Wavelength values.
    flux : array
        Flux density values.
    ra : float
        Right ascension in degrees.
    dec : float
        Declination in degrees.
    scaling: float, default ``0.86``
        Calibration of the Milky Way dust maps. Either ``0.86``
        for the Schlafly & Finkbeiner (2011) recalibration or ``1.0`` for the original
        dust map of Schlegel, Fikbeiner & Davis (1998).
    reddening_law: str, default ``fitzpatrick99``
        Reddening law. The options are: ``ccm89`` (Cardelli, Clayton & Mathis 1989), ``odonnell94`` (O’Donnell 1994),
        ``fitzpatrick99`` (Fitzpatrick 1999), ``calzetti00`` (Calzetti 2000) and ``fm07`` (Fitzpatrick & Massa 2007 with
        :math:`R_V` = 3.1.)
    dustmaps_dir : str, default ``None``
        Directory where the dust maps of Schlegel, Fikbeiner & Davis (1998) are found.
    r_v : float, default ``3.1``
        Total-to-selective extinction ratio (:math:`R_V`)
    ebv : float, default ``None``
        Colour excess (:math:`E(B-V)`). If given, this is used instead of the dust map value.

    Returns
    -------
    deredden_flux : array
        Deredden flux values.

    """
    pisco_path = piscola.__path__[0]
    if dustmaps_dir is None:
        dustmaps_dir = os.path.join(pisco_path, 'sfddata-master')

    if ebv is None:
        m = sfdmap.SFDMap(mapdir=dustmaps_dir, scaling=scaling)
        ebv = m.ebv(ra, dec)  # RA and DEC in degrees

    a_v = r_v * ebv

    rl_list = ['ccm89', 'odonnell94', 'fitzpatrick99', 'calzetti00', 'fm07']
    assert reddening_law in rl_list, f'Choose one of the available reddening laws: {rl_list}'

    if reddening_law == 'ccm89':
        ext = extinction.ccm89(wave, a_v, r_v)
    elif reddening_law == 'odonnell94':
        ext = extinction.odonnell94(wave, a_v, r_v)
    elif reddening_law == 'fitzpatrick99':
        ext = extinction.fitzpatrick99(wave, a_v, r_v)
    elif reddening_law == 'calzetti00':
        ext = extinction.calzetti00(wave, a_v, r_v)
    elif reddening_law == 'fm07':
        ext = extinction.fm07(wave, a_v)

    deredden_flux = extinction.remove(ext, flux)

    return deredden_flux
예제 #19
0
import pylab as pl
import numpy as np

from extinction import calzetti00
from extinction import apply as ext_apply

wave = np.arange(9.e2, 2.5e4)
Fv = np.ones_like(wave)

##  AV:  extinction in magnitudes at characteristic V band wavelength.
##  RV:  Ratio of total to selective extinction, A_V / E(B-V)

##  pl.plot(wave, Fv, 'k-')

##  'Redden' flux by A_V = 1.0
##  Fv   = ext_apply(calzetti00(wave, a_v=1.0, r_v=4.05, unit='aa'), Fv)
##  pl.plot(wave, Fv, 'c-')

Al = calzetti00(wave, a_v=1.0, r_v=4.05, unit='aa')  ##  Extinction [mags].
kl = ext * 4.05 / 1.0  ##  Alambda = k * Av / Rv;  See http://webast.ast.obs-mip.fr/hyperz/
##  i.e.  E(B-V) = AV / RV; -0.1 to 0.5
pl.semilogx(wave, kl)

pl.show()
예제 #20
0
def getReddeningLaw(law='fitzpatrick99',Rv=3.1,inv=False):

    import numpy as np
    from scipy import interpolate
    import extinction

    # Wavelength ranges (lambda_min - lambda_max) of the various reddening laws 
    #  (in Angstroms)...
    lambda_min = {'ccm89':          1250., 
                  'odonnell94':     1250., 
                  'calzetti00':     1200., 
                  'fitzpatrick99':   910., 
                  'fm07':            910.}
    lambda_max = {'ccm89':         33000.,
                  'odonnell94':    33000.,
                  'calzetti00':    22000.,
                  'fitzpatrick99': 60000.,
                  'fm07':          60000.}
    # We can extract the list of supported reddening laws by
    #  grabbing those that are keys within the lambda_min dictionary...
    supported_laws = lambda_min.keys()

    # If reddening law not in the the list of supported reddening laws,
    #  return an Exception...
    if law not in supported_laws: 
        print """Un-supported reddening law:  %s""" % (law)
        print 'Supported reddening laws are: ', supported_laws 
        print 'Returning exception'
        return Exception

    # Calculate and return the reddening law in either
    #  inverse wavelength form (inv=True) or in wavelength
    #  form (inv=False)...
    if inv==True:

        # Use inverse microns to call to "extinction" module
        #  and return reddening law in inverse Angstroms...

        # Calculate inverse wavelengths...
        x_lambda_min = 1.0e4/lambda_max[law]
        x_lambda_max = 1.0e4/lambda_min[law]
        x_micron = np.linspace(x_lambda_min, x_lambda_max, 2000) # microns^-1
        x_angstrom = x_micron * 1.0e-4 # Convert from microns^-1 to Anstroms^-1

        # Call appropriate reddening law function...
        if law == 'ccm89':
            r_array = Rv*extinction.ccm89(x_micron, 1.0, Rv, unit='invum')
        elif law == 'odonnell94':
            r_array = Rv*extinction.odonnell94(x_micron, 1.0, Rv, unit='invum')
        elif law == 'calzetti00':
            r_array = Rv*extinction.calzetti00(x_micron, 1.0, Rv, unit='invum')
        elif law == 'fitzpatrick99':
            r_array = Rv*extinction.fitzpatrick99(x_micron, 1.0, Rv, unit='invum')
        elif law == 'fm07':
            r_array = Rv*extinction.fm07(x_micron, 1.0, unit='invum')

        # Create interpolation function for reddening law...
        r = interpolate.interp1d(x_angstrom, r_array, 
                                 bounds_error=False, fill_value=0., kind=3)

    else:

        # Use Angstroms to call to "extinction" module
        #  and return reddening law in Angstroms...

        # Create wavelength array...
        angstrom = np.logspace(np.log10(lambda_min[law]), np.log10(lambda_max[law]), 2000)

        # Call appropriate reddening law function...
        if law == 'ccm89':
            r_array = Rv*extinction.ccm89(angstrom, 1.0, Rv, unit='aa')
        elif law == 'odonnell94':
            r_array = Rv*extinction.odonnell94(angstrom, 1.0, Rv, unit='aa')
        elif law == 'calzetti00':
            r_array = Rv*extinction.calzetti00(angstrom, 1.0, Rv, unit='aa')
        elif law == 'fitzpatrick99':
            r_array = Rv*extinction.fitzpatrick99(angstrom, 1.0, Rv, unit='aa')
        elif law == 'fm07':
            r_array = Rv*extinction.fm07(angstrom, 1.0, unit='aa')

        # Create interpolation function for reddening law...
        r = interpolate.interp1d(angstrom, r_array, 
                                 bounds_error=False, fill_value=0., kind='linear')

    # Return interpolation fucntion...
    return r
 z = 0
 for z in range(0, np.shape(red_shift)[0]):
     s = 0
     for s in range(0, np.shape(EBV)[0]):
         Ext = EBV[s]
         Av = 3.1 * Ext
         Frame = pd.read_csv('/Users/nikhil/bc03_ISEDs/bc2003_hr_' +
                             str(W[e]) + '.44',
                             comment='#',
                             header=None,
                             delim_whitespace=True)
         FrameA = np.array(Frame)
         ll = FrameA[:, 0]
         Data = FrameA[:, 1:] * L_solar
         ll_shift = ll * (1 + red_shift[z])
         Alambda = extinction.calzetti00(ll, Av, 3.1)
         Alambda_red = extinction.calzetti00(ll_shift, Av, 3.1)
         Data_fl = np.zeros(np.shape(Data))
         Data_O = np.zeros(np.shape(Data))
         w = 0
         for w in range(0, np.shape(Data)[1]):
             Data_O[:, w] = extinction.apply(Alambda_red, Data[:, w])
             Data_fl[:, w] = extinction.apply(Alambda, Data[:, w])
         #Color computation in observed frame
         lmd_shift = ll_shift
         FL_red = Data_O / (1 + red_shift[z])
         #Color_computation for ssp ages
         #Read fluxes for broad bands
         frFUV_red = FL_red[np.where((lmd_shift >= RwFUV.min())
                                     & (lmd_shift <= RwFUV.max())), :][0]
         frNUV_red = FL_red[np.where((lmd_shift >= RwNUV.min())
예제 #22
0
def render(sim, filename=None,
		   r_band='i', g_band='v', b_band='u',
		   r_scale=0.5, g_scale=1.0, b_scale=1.0,
		   dynamic_range=2.0,
		   mag_range=None,
		   width=50,
		   resolution=500,
		   starsize=None,
		   plot=True, axes=None, ret_im=False, clear=True,
		   ret_range=False, with_dust=False, z_range=50.0):
	'''
	Make a 3-color image of stars.

	The colors are based on magnitudes found using stellar Marigo
	stellar population code.  If with_dust is True, a simple dust
	screening is applied.

	Returns: If ret_im=True, an NxNx3 array representing an RGB image

	**Optional keyword arguments:**

	   *filename*: string (default: None)
		 Filename to be written to (if a filename is specified)

	   *r_band*: string (default: 'i')
		 Determines which Johnston filter will go into the image red channel

	   *g_band*: string (default: 'v')
		 Determines which Johnston filter will go into the image green channel

	   *b_band*: string (default: 'b')
		 Determines which Johnston filter will go into the image blue channel

	   *r_scale*: float (default: 0.5)
		 The scaling of the red channel before channels are combined

	   *g_scale*: float (default: 1.0)
		 The scaling of the green channel before channels are combined

	   *b_scale*: float (default: 1.0)
		 The scaling of the blue channel before channels are combined

	   *width*: float in kpc (default:50)
		 Sets the size of the image field in kpc

	   *resolution*: integer (default: 500)
	     Sets the number of pixels on the side of the image

	   *starsize*: float in kpc (default: None)
		 If not None, sets the maximum size of stars in the image

	   *ret_im*: bool (default: False)
		 if True, the NxNx3 image array is returned

	   *ret_range*: bool (default: False)
		 if True, the range of the image in mag arcsec^-2 is returned.

	   *plot*: bool (default: True)
		 if True, the image is plotted

	   *axes*: matplotlib axes object (deault: None)
		 if not None, the axes object to plot to

	   *dynamic_range*: float (default: 2.0)
		 The number of dex in luminosity over which the image brightness ranges

	   *mag_range*: float, float (default: None)
		 If provided, the brightest and faintest surface brightnesses in the range,
		 in mag arcsec^-2. Takes precedence over dynamic_range.

	   *with_dust*: bool, (default: False) 
		 If True, the image is rendered with a simple dust screening model
		 based on Calzetti's law.

	   *z_range*: float, (default: 50.0)
		 If with_dust is True this parameter specifies the z range
		 over which the column density will be calculated.
		 The default value is 50 kpc.

	'''

	if isinstance(width, str) or issubclass(width.__class__, _units.UnitBase):
		if isinstance(width, str):
			width = _units.Unit(width)
		width = width.in_units(sim['pos'].units, **sim.conversion_context())

	if starsize is not None:
		smf = filt.HighPass('smooth', str(starsize) + ' kpc')
		sim.s[smf]['smooth'] = array.SimArray(starsize, 'kpc', sim=sim)

	r = image(sim.s, qty=r_band + '_lum_den', width=width, log=False,
			  units="pc^-2", clear=False, noplot=True, resolution=resolution) * r_scale
	g = image(sim.s, qty=g_band + '_lum_den', width=width, log=False,
			  units="pc^-2", clear=False, noplot=True, resolution=resolution) * g_scale
	b = image(sim.s, qty=b_band + '_lum_den', width=width, log=False,
			  units="pc^-2", clear=False, noplot=True, resolution=resolution) * b_scale

	# convert all channels to mag arcsec^-2

	r=convert_to_mag_arcsec2(r)
	g=convert_to_mag_arcsec2(g)
	b=convert_to_mag_arcsec2(b)

	if with_dust is True:
		# render image with a simple dust absorption correction based on Calzetti's law using the gas content.
		try:
			import extinction                  
		except ImportError:
			warnings.warn(
				"Could not load extinction package. If you want to use this feature, "
				"plaese install the extinction package from here: http://extinction.readthedocs.io/en/latest/" 
				"or <via pip install extinction> or <conda install -c conda-forge extinction>", RuntimeWarning)
			return

		warm = filt.HighPass('temp',3e4)
		cool = filt.LowPass('temp',3e4)
		positive = filt.BandPass('z',-z_range,z_range) #LowPass('z',0)

		column_den_warm = image(sim.g[positive][warm], qty='rho', width=width, log=False,
			  units="kg cm^-2", clear=False, noplot=True,z_camera=z_range)
		column_den_cool = image(sim.g[positive][cool], qty='rho', width=width, log=False,
			  units="kg cm^-2", clear=False, noplot=True,z_camera=z_range)
		mh = 1.67e-27 # units kg

		cool_fac = 0.25 # fudge factor to make dust absorption not too strong
		# get the column density of gas
		col_den = np.divide(column_den_warm,mh)+np.divide(column_den_cool*cool_fac,mh)
		# get absorption coefficient
		a_v = 0.5*col_den*2e-21

		#get the central wavelength for the given band
		wavelength_avail = {'u':3571,'b':4378,'v':5466,'r':6695,'i':8565,'j':12101,
				   'h':16300,'k':21900,'U':3571,'B':4378,'V':5466,'R':6695,'I':8565,'J':12101,
				   'H':16300,'K':21900} #in Angstrom
		# effective wavelength taken from http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Generic&gname2=Johnson
		# and from https://en.wikipedia.org/wiki/Photometric_system for h, k
		
		lr,lg,lb = wavelength_avail[r_band],wavelength_avail[g_band],wavelength_avail[b_band] #in Angstrom
		wave = np.array([lb, lg, lr])

		ext_r = np.empty_like(r)
		ext_g = np.empty_like(g)
		ext_b = np.empty_like(b)
	
		for i in range(len(a_v)):
			for j in range(len(a_v[0])):
				ext = extinction.calzetti00(wave.astype(np.float), a_v[i][j].astype(np.float), 3.1, unit='aa', out=None)
				ext_r[i][j] = ext[2]
				ext_g[i][j] = ext[1]
				ext_b[i][j] = ext[0]

		r = r+ext_r
		g = g+ext_g
		b = b+ext_b

	#r,g,b = nw_scale_rgb(r,g,b)
	#r,g,b = nw_arcsinh_fit(r,g,b)

	if mag_range is None:
		rgbim, mag_max = combine(r, g, b, dynamic_range*2.5)
		mag_min = mag_max + 2.5*dynamic_range
	else:
		mag_max, mag_min = mag_range
		rgbim, mag_max = combine(r, g, b, mag_min - mag_max, mag_max)

	if plot:
		if clear:
			plt.clf()
		if axes is None:
			axes = plt.gca()

		if axes:
			axes.imshow(
				rgbim[::-1, :], extent=(-width / 2, width / 2, -width / 2, width / 2))
			axes.set_xlabel('x [' + str(sim.s['x'].units) + ']')
			axes.set_ylabel('y [' + str(sim.s['y'].units) + ']')
			plt.draw()

	if filename:
		plt.savefig(filename)

	if ret_im:
		return rgbim

	if ret_range:
		return mag_max, mag_min
    wave_aa = wave_nm * 10

    # assume spectrum
    flux_input = filter_throughput * 0 + 1

    filter_flux = numpy.trapz(y=flux_input * filter_throughput, x=wave_nm)

    r_v = 3.1
    ebv_values = numpy.logspace(-2, 0.3, 10)
    flux_values = []
    #r_v = a_v / EBV
    for ebv in ebv_values:
        a_v = r_v * ebv
        extinction_throughput = extinction.apply(
            extinction.calzetti00(wave_aa, a_v, r_v, unit='aa', out=None),
            flux_input)
        filter_extincted_flux = numpy.trapz(
            y=extinction_throughput * filter_throughput,
            x=wave_nm) / filter_flux
        flux_values.append(filter_extincted_flux)
    plt.plot(ebv_values, flux_values, label=filtername)

    ebv = 1.
    a_v = r_v * ebv
    extinction_throughput = extinction.apply(
        extinction.calzetti00(wave_aa, a_v, r_v, unit='aa', out=None),
        flux_input)
    filter_extincted_flux = numpy.trapz(
        y=extinction_throughput * filter_throughput, x=wave_nm) / filter_flux
    print('%s_factor = %.10f' % (filtername, filter_extincted_flux))