Exemplo n.º 1
0
 def update_model(self):
     if self.parent is None:
         return
     all_comp = self.parent.comps_widg.all_comp #selected_components()
     if len(all_comp) == 0:
         self.model.flux[:] = 1.
         return
     # Setup lines
     wvmin, wvmax = np.min(self.spec.dispersion), np.max(self.spec.dispersion)
     gdlin = []
     for comp in all_comp:
         for line in comp.lines:
             wvobs = (1+line.attrib['z'])*line.wrest 
             if (wvobs>wvmin) & (wvobs<wvmax):
                 line.attrib['N'] = 10.**line.attrib['logN'] / u.cm**2
                 gdlin.append(line)
     # Voigt
     #QtCore.pyqtRemoveInputHook()
     #xdb.set_trace()
     #QtCore.pyqtRestoreInputHook()
     self.model = lav.voigt_from_abslines(self.spec.dispersion, gdlin, fwhm=self.fwhm)#,debug=True)
     
     #Define arrays for plotting residuals
     if self.plot_residuals:
         self.residual_limit = self.spec.sig * self.residual_normalization_factor
         self.residual = (self.spec.flux - self.model.flux) * self.residual_normalization_factor
Exemplo n.º 2
0
    def generate_voigt(self, wave=None, **kwargs):
        """ Generate a Voigt profile model for the absorption line in
        a given spectrum.

        Parameters
        ----------
        wave : Quantity array
          Wavelength array on which to calculate the line
          Must be set if self.analy['spec'] is not filled

        Returns
        -------
        spec : XSpectrum1D
          Spectrum with the input wavelength and the absorbed flux
        """
        from linetools.analysis import voigt as lav
        # Checks
        if self.attrib['N'] < 1./u.cm**2:
            raise ValueError("Need to initialize log column density in attrib['N']")
        if self.attrib['b'] < 1.*u.km/u.s:
            raise ValueError("Need to initialize Doppler parameter in attrib['b']")
        if wave is None:
            # Assume a spectrum has been loaded already
            try:
                wave = self.analy['spec'].wavelength
            except:
                raise ('You must provide a wavelength array in generate_voigt')

        # Main call
        spec = lav.voigt_from_abslines(wave, self, **kwargs)
        return spec
Exemplo n.º 3
0
    def generate_voigt(self, wave=None, **kwargs):
        """ Generate a Voigt profile model for the absorption line in
        a given spectrum.

        Parameters
        ----------
        wave : Quantity array
          Wavelength array on which to calculate the line
          Must be set if self.analy['spec'] is not filled

        Returns
        -------
        spec : XSpectrum1D
          Spectrum with the input wavelength and the absorbed flux
        """
        from linetools.analysis import voigt as lav
        # Checks
        if self.attrib['N'] < 1. / u.cm**2:
            raise ValueError(
                "Need to initialize log column density in attrib['N']")
        if self.attrib['b'] < 1. * u.km / u.s:
            raise ValueError(
                "Need to initialize Doppler parameter in attrib['b']")
        if wave is None:
            # Assume a spectrum has been loaded already
            try:
                wave = self.analy['spec'].wavelength
            except:
                raise ('You must provide a wavelength array in generate_voigt')

        # Main call
        spec = lav.voigt_from_abslines(wave, self, **kwargs)
        return spec
Exemplo n.º 4
0
    def update_model(self):
        """Update absorption model"""
        from linetools.analysis import voigt as lav

        if len(self.abssys_widg.all_abssys) == 0:
            self.dla_model = None
            self.spec_widg.model = None
            return
        # use finer wavelength array to resolve absorption features.
        wa = self.full_model.wavelength
        # Angstroms
        # should really make this a constant velocity width array instead.
        if not self.skip_wveval:
            wa1 = np.arange(wa[0].value, wa[-1].value, self.dw) * wa.unit
        else:
            wa1 = wa
        #all_tau_model = igmlls.tau_multi_lls(wa1,
        #   self.abssys_widg.all_abssys, skip_wveval=self.skip_wveval)
        all_lines = []
        for abssys in self.abssys_widg.all_abssys:
            for iline in abssys.dla_lines:
                all_lines.append(iline)
        #QtCore.pyqtRemoveInputHook()
        #import pdb; pdb.set_trace()
        #QtCore.pyqtRestoreInputHook()
        tau_Lyman = lav.voigt_from_abslines(wa1,
                                            all_lines,
                                            ret='tau',
                                            skip_wveval=self.skip_wveval)
        '''
        # Loop on forest lines
        for forest in self.all_forest:
            tau_Lyman = lav.voigt_from_abslines(wa1, forest.lines,
                ret='tau', skip_wveval=self.skip_wveval)
            all_tau_model += tau_Lyman
        '''
        all_tau_model = tau_Lyman

        # Flux and smooth
        flux = np.exp(-1. * all_tau_model)
        if self.smooth > 0:
            if not self.skip_wveval:
                mult = np.median(np.diff(wa.value)) / self.dw
                flux = lsc.convolve_psf(flux, self.smooth * mult)
            else:
                flux = lsc.convolve_psf(flux, self.smooth)
        if not self.skip_wveval:
            self.dla_model = np.interp(wa.value, wa1.value, flux)
        else:
            self.dla_model = flux

        # Finish
        self.full_model.flux = self.dla_model * self.conti_dict['co']
        # Over-absorbed
        self.spec_widg.bad_model = np.where((self.dla_model < 0.7) & (
            self.full_model.flux <
            (self.spec_widg.spec.flux - self.spec_widg.spec.sig * 1.5)))[0]
        # Model
        self.spec_widg.model = self.full_model
Exemplo n.º 5
0
    def update_model(self):
        """Update absorption model"""
        from linetools.analysis import voigt as lav

        if len(self.abssys_widg.all_abssys) == 0:
            self.dla_model = None
            self.spec_widg.model = None
            return
        # use finer wavelength array to resolve absorption features.
        wa = self.full_model.wavelength
        # Angstroms
        # should really make this a constant velocity width array instead.
        if not self.skip_wveval:
            wa1 = np.arange(wa[0].value, wa[-1].value, self.dw) * wa.unit
        else:
            wa1 = wa
        #all_tau_model = igmlls.tau_multi_lls(wa1,
        #   self.abssys_widg.all_abssys, skip_wveval=self.skip_wveval)
        all_lines = []
        for abssys in self.abssys_widg.all_abssys:
            for iline in abssys.dla_lines:
                all_lines.append(iline)
        #QtCore.pyqtRemoveInputHook()
        #import pdb; pdb.set_trace()
        #QtCore.pyqtRestoreInputHook()
        tau_Lyman = lav.voigt_from_abslines(wa1, all_lines,
                                            ret='tau',
                                            skip_wveval=self.skip_wveval)

        '''
        # Loop on forest lines
        for forest in self.all_forest:
            tau_Lyman = lav.voigt_from_abslines(wa1, forest.lines,
                ret='tau', skip_wveval=self.skip_wveval)
            all_tau_model += tau_Lyman
        '''
        all_tau_model = tau_Lyman

        # Flux and smooth
        flux = np.exp(-1. * all_tau_model)
        if self.smooth > 0:
            if not self.skip_wveval:
                mult = np.median(np.diff(wa.value)) / self.dw
                flux = lsc.convolve_psf(flux, self.smooth * mult)
            else:
                flux = lsc.convolve_psf(flux, self.smooth)
        if not self.skip_wveval:
            self.dla_model = np.interp(wa.value, wa1.value, flux)
        else:
            self.dla_model = flux

        # Finish
        self.full_model.flux = self.dla_model * self.conti_dict['co']
        # Over-absorbed
        self.spec_widg.bad_model = np.where( (self.dla_model < 0.7) &
            (self.full_model.flux < (self.spec_widg.spec.flux-
                self.spec_widg.spec.sig*1.5)))[0]
        # Model
        self.spec_widg.model = self.full_model
Exemplo n.º 6
0
    def update_model(self):
        '''Update absorption model '''
        from linetools.analysis import voigt as lav

        if len(self.abssys_widg.all_abssys) == 0:
            self.lls_model = None
            self.spec_widg.model = None
            return
        '''
        # Regenerate (in case we have switched between multiple spectra)
        if self.spec_widg.spec.nspec > 1:
            self.full_model = XSpectrum1D.from_tuple((
                self.spec_widg.spec.wavelength,np.ones(len(self.spec_widg.spec.wavelength))))
        '''
        # use finer wavelength array to resolve absorption features.
        wa = self.full_model.wavelength
        # Angstroms
        # should really make this a constant velocity width array instead.
        if not self.skip_wveval:
            wa1 = np.arange(wa[0].value, wa[-1].value, self.dw) * wa.unit
        else:
            wa1 = wa
        all_tau_model = igmlls.tau_multi_lls(wa1,
                                             self.abssys_widg.all_abssys,
                                             skip_wveval=self.skip_wveval)

        # Loop on forest lines
        for forest in self.all_forest:
            tau_Lyman = lav.voigt_from_abslines(wa1,
                                                forest.lines,
                                                ret='tau',
                                                skip_wveval=self.skip_wveval)
            all_tau_model += tau_Lyman

        # Flux and smooth
        flux = np.exp(-1. * all_tau_model)
        if self.smooth > 0:
            if not self.skip_wveval:
                mult = np.median(np.diff(wa.value)) / self.dw
                flux = lsc.convolve_psf(flux, self.smooth * mult)
            else:
                flux = lsc.convolve_psf(flux, self.smooth)
        if not self.skip_wveval:
            self.lls_model = np.interp(wa.value, wa1.value, flux)
        else:
            self.lls_model = flux

        # Finish
        self.full_model.flux = self.lls_model * self.continuum.flux
        # Over-absorbed
        try:
            self.spec_widg.bad_model = np.where((self.lls_model < 0.7) & (
                self.full_model.flux <
                (self.spec_widg.spec.flux - self.spec_widg.spec.sig * 1.5)))[0]
        except:
            pass
        # Model
        self.spec_widg.model = self.full_model
Exemplo n.º 7
0
def dla_vary_NHI(outfil='Figures/dla_vary_NHI.pdf'):
    """ DLA profiles with NHI varying
    """
    # Wavelength array for my 'perfect' instrument
    wave = np.linspace(1160., 1270., 20000) * u.AA
    vel = (wave-1215.67*u.AA)/(1215.67*u.AA) * const.c.to('km/s')

    # Lya line
    lya = AbsLine(1215.6700*u.AA)
    #lya.attrib['N'] = 10.**(13.6)/u.cm**2
    lya.attrib['b'] = 30 * u.km/u.s
    lya.attrib['z'] = 0.

    aNHI = [20.3, 21., 21.5, 22.]

    # Start the plot
    xmnx = (-10000, 10000)
    ymnx = (0., 1.0)
    pp = PdfPages(outfil)
    fig = plt.figure(figsize=(8.0, 5.0))

    plt.clf()
    gs = gridspec.GridSpec(1,1)

    # Lya line
    ax = plt.subplot(gs[0])
    #ax.xaxis.set_minor_locator(plt.MultipleLocator(0.5))
    #ax.xaxis.set_major_locator(plt.MultipleLocator(20.))
    #ax.yaxis.set_minor_locator(plt.MultipleLocator(0.1))
    #ax.yaxis.set_major_locator(plt.MultipleLocator(0.2))
    ax.set_xlim(xmnx)
    ax.set_ylim(ymnx)
    ax.set_ylabel('Normalized Flux')
    ax.set_xlabel('Relative Velocity (km/s)') 

    lw = 1.5
    # Data
    for NHI in aNHI:
        lyai = copy.deepcopy(lya)
        lyai.attrib['N'] = 10**NHI / u.cm**2
        f_obsi = ltav.voigt_from_abslines(wave, [lyai])
        ax.plot(vel, f_obsi.flux, linewidth=lw, 
            label=r'$\log N_{\rm HI} = $'+'{:0.2f}'.format(NHI))

    # Legend
    legend = plt.legend(loc='lower left', scatterpoints=1, borderpad=0.3, 
        handletextpad=0.3, fontsize='large', numpoints=1)
    xputils.set_fontsize(ax, 17.)
    # Layout and save
    print('Writing {:s}'.format(outfil))
    plt.tight_layout(pad=0.2,h_pad=0.0,w_pad=0.4)
    plt.subplots_adjust(hspace=0)
    pp.savefig(bbox_inches='tight')
    plt.close()
    # Finish
    pp.close()
Exemplo n.º 8
0
def test_voigt_sngl_tau():
    # Wavelength array
    wave = np.linspace(3644, 3650, 100) * u.AA
    imn = np.argmin(np.abs(wave.value - 3647))
    # HI line
    abslin = AbsLine(1215.670 * u.AA, z=2.)
    abslin.attrib['N'] = 10**14. / u.cm**2
    abslin.attrib['b'] = 25. * u.km / u.s
    # Tau
    tau = lav.voigt_from_abslines(wave, abslin, ret='tau')
    np.testing.assert_allclose(tau[imn], 2.9681283001576779)
Exemplo n.º 9
0
def test_voigt_sngl_tau():
    # Wavelength array
    wave = np.linspace(3644, 3650, 100)*u.AA
    imn = np.argmin(np.abs(wave.value-3647))
    # HI line
    abslin = AbsLine(1215.670*u.AA, z=2.)
    abslin.attrib['N'] = 10**14./u.cm**2
    abslin.attrib['b'] = 25.*u.km/u.s
    # Tau
    tau = lav.voigt_from_abslines(wave,abslin,ret='tau')
    np.testing.assert_allclose(tau[imn], 2.9681283001576779)
Exemplo n.º 10
0
    def flux_model(self, spec, smooth=0):
        """ Generate a LLS model given an input spectrum

        Parameters
        ----------
        spec :  Spectrum1D
        smooth : int, optional
          Number of pixels to smooth by

        Returns
        -------
        model : XSpectrum1D
          Output model is passed back as a Spectrum 
        """
        from linetools.analysis import voigt as lav

        # Energies in LLS rest-frame
        wv_rest = spec.wavelength / (self.zabs + 1)
        energy = wv_rest.to(u.eV, equivalencies=u.spectral())

        # Get photo_cross and calculate tau
        tau_LL = (10.**self.NHI / u.cm**2) * ltaa.photo_cross(1, 1, energy)

        # Check for lines
        if 'lls_lines' not in self.__dict__.keys():
            self.fill_lls_lines()

        tau_Lyman = lav.voigt_from_abslines(spec.wavelength,
                                            self.lls_lines,
                                            ret='tau')

        # Combine
        tau_model = tau_LL + tau_Lyman

        # Kludge around the limit
        pix_LL = np.argmin(np.fabs(wv_rest - 911.3 * u.AA))
        pix_kludge = np.where((wv_rest > 911.5 * u.AA)
                              & (wv_rest < 912.8 * u.AA))[0]
        tau_model[pix_kludge] = tau_model[pix_LL]

        # Fill in flux
        model = spec.copy()
        model.flux = np.exp(-1. * tau_model).value

        # Smooth?
        if smooth > 0:
            model.gauss_smooth(smooth)

        # Return
        return model
Exemplo n.º 11
0
def test_voigt_multi_line():
    # Wavelength array
    wave = np.linspace(3644, 3650, 100)*u.AA
    imn = np.argmin(np.abs(wave.value-3646.2))
    # HI line
    abslin = AbsLine(1215.670*u.AA, z=2.)
    abslin.attrib['N'] = 10**17.5/u.cm**2
    abslin.attrib['b'] = 20.*u.km/u.s
    # DI line
    abslin2 = AbsLine('DI 1215', z=2.)
    abslin2.attrib['N'] = 10**13./u.cm**2
    abslin2.attrib['b'] = 15.*u.km/u.s
    # Voigt
    vmodel3 = lav.voigt_from_abslines(wave,[abslin,abslin2])
    np.testing.assert_allclose(vmodel3.flux[imn].value,0.5715512949324375)
Exemplo n.º 12
0
def test_voigt_multi_line():
    # Wavelength array
    wave = np.linspace(3644, 3650, 100) * u.AA
    imn = np.argmin(np.abs(wave.value - 3646.2))
    # HI line
    abslin = AbsLine(1215.670 * u.AA, z=2.)
    abslin.attrib['N'] = 10**17.5 / u.cm**2
    abslin.attrib['b'] = 20. * u.km / u.s
    # DI line
    abslin2 = AbsLine('DI 1215', z=2.)
    abslin2.attrib['N'] = 10**13. / u.cm**2
    abslin2.attrib['b'] = 15. * u.km / u.s
    # Voigt
    vmodel3 = lav.voigt_from_abslines(wave, [abslin, abslin2])
    np.testing.assert_allclose(vmodel3.flux[imn].value, 0.5715512949324375)
Exemplo n.º 13
0
def generate_tau(iwave, HIlines, HI_comps, kludge=True):
    """Generate optical depth array given lines and components

    Parameters:
    -----------

    iwave : Quantity array
      Input Spectrum wavelengths
    HIlines : list of AbsLines
    HI_comps : QTable of components
    kludge : bool, optional
      Kludge the opacity

    Returns:
    --------
    tau : ndarray
      Optical depth at subgrid wavelengths.  Will need to rebin back
    """
    # Rebin to subgrid

    wmin = np.min(iwave.to('AA').value)
    wmax = np.max(iwave.to('AA').value)
    nsub = int(np.round((np.log10(wmax) - np.log10(wmin)) / 1.449E-6)) + 1
    wave = 10.**(np.log10(wmin) + np.arange(nsub) * 1.449E-6) * u.AA

    # Voigt for Lyman series
    tau_Lyman = lav.voigt_from_abslines(wave, HIlines, fwhm=0., ret='tau')

    # Continuum opacity
    LL_comps = HI_comps['lgNHI'] > 15.0
    tau_LL = np.zeros(wave.size)
    for row in HI_comps[LL_comps]:
        # Energies in LLS rest-frame
        wv_rest = wave / (row['z'] + 1)
        energy = wv_rest.to(u.eV, equivalencies=u.spectral())
        # Get photo_cross and calculate tau
        itau_LL = (10.**row['lgNHI'] / u.cm**2) * photo_cross(1, 1, energy)
        # Kludge around the limit
        if kludge:
            pix_LL = np.argmin(np.fabs(wv_rest - 911.3 * u.AA))
            pix_kludge = np.where((wv_rest > 911.5 * u.AA)
                                  & (wv_rest < 912.8 * u.AA))[0]
            itau_LL[pix_kludge] = itau_LL[pix_LL]
        # Sum
        tau_LL += itau_LL.decompose().value
    # Total
    return wave, tau_LL + tau_Lyman
Exemplo n.º 14
0
    def flux_model(self, spec, smooth=0):
        """ Generate a LLS model given an input spectrum

        Parameters
        ----------
        spec :  Spectrum1D
        smooth : int, optional
          Number of pixels to smooth by

        Returns
        -------
        model : XSpectrum1D
          Output model is passed back as a Spectrum 
        """
        from linetools.analysis import voigt as lav

        # Energies in LLS rest-frame
        wv_rest = spec.dispersion / (self.zabs+1)
        energy = wv_rest.to(u.eV, equivalencies=u.spectral())

        # Get photo_cross and calculate tau
        tau_LL = (10.**self.NHI / u.cm**2) * ltaa.photo_cross(1, 1, energy)

        # Check for lines
        if 'lls_lines' not in self.__dict__.keys():
            self.fill_lls_lines()

        tau_Lyman = lav.voigt_from_abslines(spec.dispersion, self.lls_lines, ret='tau')

        # Combine
        tau_model = tau_LL + tau_Lyman

        # Kludge around the limit
        pix_LL = np.argmin(np.fabs( wv_rest- 911.3*u.AA))
        pix_kludge = np.where((wv_rest > 911.5*u.AA) & (wv_rest < 912.8*u.AA))[0]
        tau_model[pix_kludge] = tau_model[pix_LL]
        
        # Fill in flux
        model = spec.copy()
        model.flux = np.exp(-1. * tau_model).value

        # Smooth?
        if smooth > 0:
            model.gauss_smooth(smooth)

        # Return
        return model
Exemplo n.º 15
0
def generate_tau(iwave, HIlines, HI_comps, kludge=True):
    """Generate optical depth array given lines and components

    Parameters:
    -----------

    iwave : Quantity array
      Input Spectrum wavelengths
    HIlines : list of AbsLines
    HI_comps : QTable of components
    kludge : bool, optional
      Kludge the opacity

    Returns:
    --------
    tau : ndarray
      Optical depth at subgrid wavelengths.  Will need to rebin back
    """
    # Rebin to subgrid

    wmin = np.min(iwave.to('AA').value)
    wmax = np.max(iwave.to('AA').value)
    nsub = int(np.round( (np.log10(wmax)- np.log10(wmin)) / 1.449E-6)) + 1
    wave = 10.**(np.log10(wmin) + np.arange(nsub)*1.449E-6) * u.AA

    # Voigt for Lyman series
    tau_Lyman = lav.voigt_from_abslines(wave,HIlines,fwhm=0.,ret='tau')

    # Continuum opacity
    LL_comps = HI_comps['lgNHI'] > 15.0
    tau_LL = np.zeros(wave.size)
    for row in HI_comps[LL_comps]:
        # Energies in LLS rest-frame
        wv_rest = wave / (row['z']+1)
        energy = wv_rest.to(u.eV, equivalencies=u.spectral())
        # Get photo_cross and calculate tau
        itau_LL = (10.**row['lgNHI'] / u.cm**2) * photo_cross(1,1,energy)
        # Kludge around the limit
        if kludge:
            pix_LL = np.argmin(np.fabs(wv_rest- 911.3*u.AA))
            pix_kludge = np.where((wv_rest > 911.5*u.AA) & (wv_rest < 912.8*u.AA))[0]
            itau_LL[pix_kludge] = itau_LL[pix_LL]
        # Sum
        tau_LL += itau_LL
    # Total
    return wave, tau_LL + tau_Lyman
Exemplo n.º 16
0
def tau_multi_lls(wave, all_lls, **kwargs):
    """Calculate opacities on an input observed wavelength grid

    Parameters
    ----------
    wave : Quantity array
      Wavelengths
    all_lls : list
      List of LLS Class
    **kwargs : dict
      extra keywords go to lav.voigt_from_abslines

    Returns
    -------
    tau : ndarray
      Optical depth values at input wavelengths
    """
    from linetools.analysis import voigt as lav
    #
    all_tau_model = np.zeros(len(wave))
    # Loop on LLS
    for lls in all_lls:
        # LL
        wv_rest = wave / (lls.zabs + 1)
        energy = wv_rest.to(u.eV, equivalencies=u.spectral())
        # Get photo_cross and calculate tau
        tau_LL = (10.**lls.NHI / u.cm**2) * ltaa.photo_cross(1, 1, energy)

        # Lyman
        tau_Lyman = lav.voigt_from_abslines(wave,
                                            lls.lls_lines,
                                            ret='tau',
                                            **kwargs)
        tau_model = tau_LL + tau_Lyman

        # Kludge around the limit
        pix_LL = np.argmin(np.fabs(wv_rest - 911.3 * u.AA))
        pix_kludge = np.where((wv_rest > 911.5 * u.AA)
                              & (wv_rest < 912.8 * u.AA))[0]
        tau_model[pix_kludge] = tau_model[pix_LL]
        # Add
        all_tau_model += tau_model
    # Return
    return all_tau_model
Exemplo n.º 17
0
def tau_multi_lls(wave, all_lls, **kwargs):
    """Calculate opacities on an input observed wavelength grid

    Parameters
    ----------
    wave : Quantity array
      Wavelengths
    all_lls : list
      List of LLS Class
    **kwargs : dict
      extra keywords go to lav.voigt_from_abslines

    Returns
    -------
    tau : ndarray
      Optical depth values at input wavelengths
    """
    from linetools.analysis import voigt as lav
    #
    all_tau_model = np.zeros(len(wave))
    # Loop on LLS
    for lls in all_lls:
        # LL
        wv_rest = wave / (lls.zabs+1)
        energy = wv_rest.to(u.eV, equivalencies=u.spectral())
        # Get photo_cross and calculate tau
        tau_LL = (10.**lls.NHI / u.cm**2) * ltaa.photo_cross(1,1,energy)

        # Lyman
        tau_Lyman = lav.voigt_from_abslines(wave, lls.lls_lines, ret='tau', **kwargs)
        tau_model = tau_LL + tau_Lyman

        # Kludge around the limit
        pix_LL = np.argmin(np.fabs( wv_rest- 911.3*u.AA ))
        pix_kludge = np.where((wv_rest > 911.5*u.AA) & (wv_rest < 912.8*u.AA))[0]
        tau_model[pix_kludge] = tau_model[pix_LL]
        # Add
        all_tau_model += tau_model
    # Return
    return all_tau_model
Exemplo n.º 18
0
def example_ew(outfil='Figures/example_ew.pdf'):
    """ A simple example of EW
    """

    # Generate a simple Lya line
    lya = AbsLine(1215.6700 * u.AA)
    NHI = 13.6
    bval = 30.
    lya.attrib['N'] = 10.**(NHI) / u.cm**2
    lya.attrib['b'] = bval * u.km / u.s
    lya.attrib['z'] = 0.

    # Spectrum
    wave = np.linspace(1180., 1250., 20000) * u.AA
    f_obs = ltav.voigt_from_abslines(wave, [lya])
    f_obs.sig = 0.1 * np.ones(f_obs.npix)

    # Measure EW
    lya.analy['spec'] = f_obs
    lya.analy['wvlim'] = [1210., 1220] * u.AA
    lya.measure_ew()

    # Initialize
    xmnx = (1214.2, 1217.2)
    ymnx = (-0.05, 1.08)
    ms = 7.

    # Start the plot
    pp = PdfPages(outfil)
    fig = plt.figure(figsize=(8.5, 3.7))

    plt.clf()
    gs = gridspec.GridSpec(1, 2)

    # Lya line
    ax = plt.subplot(gs[0, 0])
    #ax.xaxis.set_minor_locator(plt.MultipleLocator(0.5))
    #ax.xaxis.set_major_locator(plt.MultipleLocator(20.))
    #ax.yaxis.set_minor_locator(plt.MultipleLocator(0.1))
    #ax.yaxis.set_major_locator(plt.MultipleLocator(0.2))
    ax.set_xlim(xmnx)
    ax.set_ylim(ymnx)
    ax.set_ylabel('Normalized Flux')
    ax.set_xlabel('Wavelength (Angstroms)')

    lw = 2
    ax.plot(f_obs.wavelength, f_obs.flux, 'k', linewidth=lw)
    ax.fill_between(f_obs.wavelength.value,
                    f_obs.flux.value,
                    np.ones(f_obs.npix),
                    color='blue',
                    alpha=0.7)

    # Label
    csz = 12.
    cNHI = '{:0.1f}'.format(NHI)
    ax.text(0.05,
            0.2,
            r'$N_{\rm HI} = 10^{' + cNHI + r'} \rm cm^{-2}$',
            transform=ax.transAxes,
            size=csz,
            ha='left')  #, bbox={'facecolor':'white'})
    ax.text(0.05,
            0.12,
            r'$b = $' + '{:d} km/s'.format(int(bval)),
            transform=ax.transAxes,
            size=csz,
            ha='left')  #, bbox={'facecolor':'white'})
    ax.text(0.05,
            0.04,
            r'$W_\lambda = $' + '{:0.2f} Ang'.format(lya.attrib['EW'].value),
            transform=ax.transAxes,
            size=csz,
            ha='left')  #, bbox={'facecolor':'white'})

    # EW panel
    ax = plt.subplot(gs[0, 1])
    ax.set_xlim(xmnx)
    ax.set_ylim(ymnx)
    ax.set_ylabel('Normalized Flux')
    ax.set_xlabel('Wavelength (Angstroms)')

    xval = [0] + [1215.67 - lya.attrib['EW'].value / 2
                  ] * 2 + [1215.67 + lya.attrib['EW'].value / 2] * 2 + [1500]
    ax.plot(xval, [1, 1, 0, 0, 1, 1], 'k', linewidth=lw)
    ax.fill_between(
        np.array([lya.attrib['EW'].value / 2] * 2) * np.array([-1, 1]) +
        1215.67, [0, 0], [1, 1],
        color='red',
        alpha=0.7)

    # Layout and save
    print('Writing {:s}'.format(outfil))
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.4)
    plt.subplots_adjust(hspace=0)
    pp.savefig(bbox_inches='tight')
    plt.close()
    # Finish
    pp.close()
Exemplo n.º 19
0
def dla_vary_NHI(outfil='Figures/dla_vary_NHI.pdf'):
    """ DLA profiles with NHI varying
    """
    # Wavelength array for my 'perfect' instrument
    wave = np.linspace(1160., 1270., 20000) * u.AA
    vel = (wave - 1215.67 * u.AA) / (1215.67 * u.AA) * const.c.to('km/s')

    # Lya line
    lya = AbsLine(1215.6700 * u.AA)
    #lya.attrib['N'] = 10.**(13.6)/u.cm**2
    lya.attrib['b'] = 30 * u.km / u.s
    lya.attrib['z'] = 0.

    aNHI = [20.3, 21., 21.5, 22.]

    # Start the plot
    xmnx = (-10000, 10000)
    ymnx = (0., 1.0)
    pp = PdfPages(outfil)
    fig = plt.figure(figsize=(8.0, 5.0))

    plt.clf()
    gs = gridspec.GridSpec(1, 1)

    # Lya line
    ax = plt.subplot(gs[0])
    #ax.xaxis.set_minor_locator(plt.MultipleLocator(0.5))
    #ax.xaxis.set_major_locator(plt.MultipleLocator(20.))
    #ax.yaxis.set_minor_locator(plt.MultipleLocator(0.1))
    #ax.yaxis.set_major_locator(plt.MultipleLocator(0.2))
    ax.set_xlim(xmnx)
    ax.set_ylim(ymnx)
    ax.set_ylabel('Normalized Flux')
    ax.set_xlabel('Relative Velocity (km/s)')

    lw = 1.5
    # Data
    for NHI in aNHI:
        lyai = copy.deepcopy(lya)
        lyai.attrib['N'] = 10**NHI / u.cm**2
        f_obsi = ltav.voigt_from_abslines(wave, [lyai])
        ax.plot(vel,
                f_obsi.flux,
                linewidth=lw,
                label=r'$\log N_{\rm HI} = $' + '{:0.2f}'.format(NHI))

    # Legend
    legend = plt.legend(loc='lower left',
                        scatterpoints=1,
                        borderpad=0.3,
                        handletextpad=0.3,
                        fontsize='large',
                        numpoints=1)
    xputils.set_fontsize(ax, 17.)
    # Layout and save
    print('Writing {:s}'.format(outfil))
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.4)
    plt.subplots_adjust(hspace=0)
    pp.savefig(bbox_inches='tight')
    plt.close()
    # Finish
    pp.close()
Exemplo n.º 20
0
def dla_deviation(outfil='Figures/dla_deviation.pdf'):
    """ Deviations from Voigt (Lee 2003)
    """
    # Wavelength array for my 'perfect' instrument
    wave = np.linspace(1140., 1290., 20000) * u.AA
    vel = (wave - 1215.67 * u.AA) / (1215.67 * u.AA) * const.c.to('km/s')
    nu = (const.c / wave).to('Hz')

    # Lya line
    lya = AbsLine(1215.6700 * u.AA)
    lya.attrib['N'] = 10.**(22) / u.cm**2
    lya.attrib['b'] = 30 * u.km / u.s
    lya.attrib['z'] = 0.

    # Lee
    sigmaT = (6.65e-29 * u.m**2).to('cm**2')  # Approximate!
    f_jk = 0.4162
    nu_jk = (const.c / lya.wrest).to('Hz')

    def eval_cross_Lee(nu):
        return sigmaT * (f_jk /
                         2)**2 * (nu_jk /
                                  (nu - nu_jk))**2 * (1 - 1.792 *
                                                      (nu - nu_jk) / nu_jk)

    tau_lee = lya.attrib['N'] * eval_cross_Lee(nu)
    flux_lee = np.exp(-1 * tau_lee.value)
    # Start the plot
    xmnx = (-15000, 15000)
    ymnx = (0., 1.0)
    pp = PdfPages(outfil)
    fig = plt.figure(figsize=(8.0, 5.0))

    plt.clf()
    gs = gridspec.GridSpec(1, 1)

    # Lya line
    ax = plt.subplot(gs[0])
    #ax.xaxis.set_minor_locator(plt.MultipleLocator(0.5))
    #ax.xaxis.set_major_locator(plt.MultipleLocator(20.))
    #ax.yaxis.set_minor_locator(plt.MultipleLocator(0.1))
    #ax.yaxis.set_major_locator(plt.MultipleLocator(0.2))
    ax.set_xlim(xmnx)
    ax.set_ylim(ymnx)
    ax.set_ylabel('Normalized Flux')
    ax.set_xlabel('Relative Velocity (km/s)')

    f_voigt = ltav.voigt_from_abslines(wave, [lya])
    lw = 2
    ax.plot(vel,
            f_voigt.flux,
            'k',
            linewidth=lw,
            label=r'Voigt: $\log N_{\rm HI} = 22$')
    ax.plot(vel,
            flux_lee,
            'r',
            linewidth=lw,
            label=r'Lee2003: $\log N_{\rm HI} = 22$')

    # Legend
    legend = plt.legend(loc='lower left',
                        scatterpoints=1,
                        borderpad=0.3,
                        handletextpad=0.3,
                        fontsize='large',
                        numpoints=1)
    xputils.set_fontsize(ax, 17.)
    # Layout and save
    print('Writing {:s}'.format(outfil))
    plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.4)
    plt.subplots_adjust(hspace=0)
    pp.savefig(bbox_inches='tight')
    plt.close()
    # Finish
    pp.close()
Exemplo n.º 21
0
def fig_lya_lines(outfil='Figures/fig_lya_lines.pdf'):
    """ Plot the LLS models

    Parameters
    ----------

    Returns
    -------

    """
    #
    # Initialize
    ms = 7.

    # Start the plot
    if outfil is not None:
        pp = PdfPages(outfil)

    # Dummy line
    lya = AbsLine(1215.6700 * u.AA)
    lya.attrib['N'] = 10.**(13.6) / u.cm**2
    b0 = 20
    lya.attrib['b'] = b0 * u.km / u.s
    lya.attrib['z'] = 0.

    # Wavelength array
    wave = np.linspace(1200., 1230., 10000) * u.AA

    fig = plt.figure(figsize=(8, 5))
    plt.clf()
    gs = gridspec.GridSpec(1, 2)

    lsz = 12.
    # NHI varies first
    ax = plt.subplot(gs[0])
    NHIs = [12., 13., 14., 15.]
    # Loop
    for jj, NHI in enumerate(NHIs):
        lya.attrib['N'] = 10.**(NHI) / u.cm**2
        f_obs = ltav.voigt_from_abslines(wave, [lya])

        # Plot
        ax.plot(f_obs.wavelength,
                f_obs.flux,
                '-',
                label=r'log $N_{\rm HI}$ ' + '= {:g}'.format(NHI))

    legend = plt.legend(loc='upper right',
                        scatterpoints=1,
                        borderpad=0.3,
                        handletextpad=0.3,
                        fontsize='small',
                        numpoints=1,
                        title=r'$b = $' + '{:g} km/s'.format(b0))
    ax.xaxis.set_major_locator(plt.MultipleLocator(1.))
    ax.xaxis.set_major_locator(MaxNLocator(integer=True))
    x_formatter = mpl.ticker.ScalarFormatter(useOffset=False)
    ax.xaxis.set_major_formatter(x_formatter)
    ax.minorticks_on()
    ax.set_xlabel('Wavelength (Ang)')
    ax.set_xlim(1214.8, 1216.6)
    ax.set_ylabel('Normalized Flux')

    # Now b
    ax = plt.subplot(gs[1])
    N0 = 14.
    lya.attrib['N'] = 10.**(N0) / u.cm**2
    bvals = [10., 30., 50.]
    # Loop
    for jj, bval in enumerate(bvals):
        lya.attrib['b'] = bval * u.km / u.s
        f_obs = ltav.voigt_from_abslines(wave, [lya])

        # Plot
        velo = f_obs.relative_vel(lya.wrest)
        ax.plot(velo,
                f_obs.flux,
                '-',
                label=r'log $N_{\rm HI}$ ' + '= {:g}'.format(NHI))
        #ax.plot(f_obs.wavelength, f_obs.flux, '-', label=r'$b$ '+'= {:g} km/s'.format(bval))

    legend = plt.legend(loc='lower right',
                        scatterpoints=1,
                        borderpad=0.3,
                        handletextpad=0.3,
                        fontsize='small',
                        numpoints=1,
                        title=r'log $N_{\rm HI} =$' + '{:g}'.format(N0))
    ax.set_xlabel('Relative Velocity (km/s)')
    ax.set_xlim(-150., 150.)
    ax.set_ylabel('Normalized Flux')

    # Layout and save
    print('Writing {:s}'.format(outfil))
    plt.tight_layout(pad=0.2, h_pad=0.1, w_pad=0.2)
    pp.savefig(bbox_inches='tight')
    plt.close()
    # Finish
    pp.close()
Exemplo n.º 22
0
def fig_lya_lines(outfil='Figures/fig_lya_lines.pdf'):
    """ Plot the LLS models

    Parameters
    ----------

    Returns
    -------

    """
    # 
    # Initialize
    ms = 7.
    
    # Start the plot
    if outfil is not None:
        pp = PdfPages(outfil)

    # Dummy line
    lya = AbsLine(1215.6700*u.AA)
    lya.attrib['N'] = 10.**(13.6)/u.cm**2
    b0 = 20
    lya.attrib['b'] = b0 * u.km/u.s
    lya.attrib['z'] = 0.

    # Wavelength array
    wave = np.linspace(1200., 1230., 10000) * u.AA

    fig = plt.figure(figsize=(8, 5))
    plt.clf()
    gs = gridspec.GridSpec(1, 2)

    lsz = 12.
    # NHI varies first
    ax = plt.subplot(gs[0])
    NHIs = [12., 13., 14., 15.]
    # Loop
    for jj, NHI in enumerate(NHIs):
        lya.attrib['N'] = 10.**(NHI)/u.cm**2
        f_obs = ltav.voigt_from_abslines(wave, [lya])

        # Plot
        ax.plot(f_obs.wavelength, f_obs.flux, '-', label=r'log $N_{\rm HI}$ '+'= {:g}'.format(NHI))

    legend = plt.legend(loc='upper right', scatterpoints=1, borderpad=0.3,
                        handletextpad=0.3, fontsize='small', numpoints=1, 
                        title=r'$b = $'+'{:g} km/s'.format(b0))
    ax.xaxis.set_major_locator(plt.MultipleLocator(1.))
    ax.xaxis.set_major_locator(MaxNLocator(integer=True))
    x_formatter = mpl.ticker.ScalarFormatter(useOffset=False)
    ax.xaxis.set_major_formatter(x_formatter)
    ax.minorticks_on()
    ax.set_xlabel('Wavelength (Ang)')
    ax.set_xlim(1214.8, 1216.6)
    ax.set_ylabel('Normalized Flux')

    # Now b
    ax = plt.subplot(gs[1])
    N0 = 14.
    lya.attrib['N'] = 10.**(N0)/u.cm**2
    bvals = [10., 30., 50.]
    # Loop
    for jj, bval in enumerate(bvals):
        lya.attrib['b'] = bval*u.km/u.s
        f_obs = ltav.voigt_from_abslines(wave, [lya])

        # Plot
        velo = f_obs.relative_vel(lya.wrest)
        ax.plot(velo, f_obs.flux, '-', label=r'log $N_{\rm HI}$ '+'= {:g}'.format(NHI))
        #ax.plot(f_obs.wavelength, f_obs.flux, '-', label=r'$b$ '+'= {:g} km/s'.format(bval))

    legend = plt.legend(loc='lower right', scatterpoints=1, borderpad=0.3,
                        handletextpad=0.3, fontsize='small', numpoints=1, 
                        title=r'log $N_{\rm HI} =$'+'{:g}'.format(N0))
    ax.set_xlabel('Relative Velocity (km/s)')
    ax.set_xlim(-150., 150.)
    ax.set_ylabel('Normalized Flux')

    # Layout and save
    print('Writing {:s}'.format(outfil))
    plt.tight_layout(pad=0.2,h_pad=0.1,w_pad=0.2)
    pp.savefig(bbox_inches='tight')
    plt.close()
    # Finish
    pp.close()
Exemplo n.º 23
0
    def __init__(self,
                 ispec,
                 guessfile=None,
                 parent=None,
                 zsys=None,
                 norm=None,
                 exten=None,
                 rsp_kwargs={},
                 unit_test=False,
                 screen_scale=1.,
                 **kwargs):
        QMainWindow.__init__(self, parent)
        """
        ispec = str, XSpectrum1D or tuple of arrays
          Input spectrum or spectrum filename.  If tuple then (wave,
          fx), (wave, fx, sig) or (wave, fx, sig, co)
        guessfile : str, optional
          name of the .json file generated with igmguesses GUI in Pyigm (see https://github.com/pyigm/pyigm/blob/master/docs/igmguesses.rst)
          if not None - overplot fitted line profiles from igmguesses
        parent : Widget parent, optional
        zsys : float, optional
          intial redshift
        exten : int, optional
          extension for the spectrum in multi-extension FITS file
        norm : bool, optional
          True if the spectrum is normalized
        screen_scale : float, optional
          Scale the default sizes for the gui size
        """
        #reload(ltgl)
        #reload(ltgsp)
        # INIT
        #QtCore.pyqtRemoveInputHook()
        #xdb.set_trace()
        #QtCore.pyqtRestoreInputHook()

        self.scale = screen_scale

        # Needed to avoid crash in large spectral files
        rcParams['agg.path.chunksize'] = 20000
        rcParams[
            'axes.formatter.useoffset'] = False  # avoid scientific notation in axes tick labels

        # Build a widget combining several others
        self.main_widget = QWidget()

        # Status bar
        self.create_status_bar()

        # Grab the pieces and tie together
        self.pltline_widg = ltgl.PlotLinesWidget(status=self.statusBar,
                                                 init_z=zsys,
                                                 screen_scale=self.scale)
        self.pltline_widg.setMaximumWidth(300 * self.scale)

        ## Abs sys
        abs_sys = None
        voigtsfit = None
        if guessfile is not None:
            # Load
            ism = LineList('ISM')
            igm_guess = ltu.loadjson(guessfile)
            comps = []
            for key in igm_guess['cmps'].keys():
                comp = AbsComponent.from_dict(igm_guess['cmps'][key],
                                              chk_vel=False,
                                              linelist=ism)
                comps.append(comp)
            abs_sys = ltiu.build_systems_from_components(
                comps, vsys=500. * u.km /
                u.s)  # ,chk_z=False)  ### 100000.*u.km/u.s   ok

            ### voigt fit - added
            # Spectrum
            spec, spec_fil = ltgu.read_spec(ispec,
                                            exten=exten,
                                            norm=norm,
                                            rsp_kwargs=rsp_kwargs)

            voigtsfit = np.asarray([0] * len(spec.wavelength))
            alllines = []
            for iabs_sys in abs_sys:
                lines = iabs_sys.list_of_abslines()
                alllines = alllines + lines
            if len(alllines) > 0:
                voigtsfit = lav.voigt_from_abslines(spec.wavelength,
                                                    alllines,
                                                    fwhm=3.).flux.value

            if not norm:
                voigtsfit = voigtsfit * spec.co

        # Hook the spec widget to Plot Line
        self.spec_widg = ltgsp.ExamineSpecWidget(ispec,
                                                 guessfile=guessfile,
                                                 voigtsfit=voigtsfit,
                                                 status=self.statusBar,
                                                 parent=self,
                                                 llist=self.pltline_widg.llist,
                                                 zsys=zsys,
                                                 norm=norm,
                                                 exten=exten,
                                                 abs_sys=abs_sys,
                                                 screen_scale=self.scale,
                                                 rsp_kwargs=rsp_kwargs,
                                                 **kwargs)
        # Reset redshift from spec
        if zsys is None:
            if hasattr(self.spec_widg.spec, 'z'):
                self.pltline_widg.setz(
                    str(self.spec_widg.spec.z[self.spec_widg.select]))
        # Auto set line list if spec has proper object type
        if hasattr(self.spec_widg.spec, 'stypes'):
            if self.spec_widg.spec.stypes[
                    self.spec_widg.select].lower() == 'galaxy':
                self.pltline_widg.llist = ltgu.set_llist(
                    'Galaxy', in_dict=self.pltline_widg.llist)
            elif self.spec_widg.spec.stypes[
                    self.spec_widg.select].lower() == 'absorber':
                self.pltline_widg.llist = ltgu.set_llist(
                    'Strong', in_dict=self.pltline_widg.llist)
            self.pltline_widg.llist['Plot'] = True
            idx = self.pltline_widg.lists.index(
                self.pltline_widg.llist['List'])
            self.pltline_widg.llist_widget.setCurrentRow(idx)
        #
        self.pltline_widg.spec_widg = self.spec_widg
        # Multi spec
        self.mspec_widg = ltgsp.MultiSpecWidget(self.spec_widg)

        self.spec_widg.canvas.mpl_connect('button_press_event', self.on_click)

        # Layout

        # Extras
        extras = QWidget()
        extras.setMinimumWidth(180 * self.scale)
        extras.setMaximumWidth(280 * self.scale)
        vbox = QVBoxLayout()
        qbtn = QPushButton(self)
        qbtn.setText('Quit')
        qbtn.clicked.connect(self.quit)
        vbox.addWidget(self.pltline_widg)
        vbox.addWidget(self.mspec_widg)
        vbox.addWidget(qbtn)
        extras.setLayout(vbox)

        # Main window
        hbox = QHBoxLayout()
        hbox.addWidget(self.spec_widg)
        hbox.addWidget(extras)

        self.main_widget.setLayout(hbox)

        # Point MainWindow
        self.setCentralWidget(self.main_widget)
        if unit_test:
            self.quit()
Exemplo n.º 24
0
def redshift(outfil='Figures/redshift.pdf'):
    """ Series of plots illustrating redshift in the Lya forest
    """
    lrest = np.array([900., 1250])  # Ang
    zem = 3.
    toff = 0.15
    yqso = 0.7
    sqso = 35

    # QSO lines
    qsolya = AbsLine(1215.6700 * u.AA)
    qsolya.attrib['N'] = 10.**(16.0) / u.cm**2
    qsolya.attrib['b'] = 40 * u.km / u.s
    qsolya.attrib['z'] = zem
    qsolyb = AbsLine('HI 1025')
    qsolyb.attrib['N'] = qsolya.attrib['N']
    qsolyb.attrib['b'] = qsolya.attrib['b']
    qsolyb.attrib['z'] = qsolya.attrib['z']

    def tick_function(z, X):
        V = X * (1 + z)
        return ["{:d}".format(int(round(x))) for x in V]

    def add_lines(axi, z):
        wvtwo = (1 + z) * 1215.67 / (1 + zem)
        axi.scatter([wvtwo], [yqso],
                    marker='o',
                    facecolor='none',
                    edgecolor='green',
                    s=sqso * 5)
        axi.text(wvtwo,
                 yqso - 1.7 * toff,
                 'HI Gas (z={:0.1f})'.format(z),
                 color='green',
                 ha='center')
        #
        twolya = copy.deepcopy(qsolya)
        twolya.attrib['z'] = z
        twolyb = copy.deepcopy(qsolyb)
        twolyb.attrib['z'] = z
        return [twolya, twolyb]

    # Telfer
    telfer = pyicq.get_telfer_spec()

    # Start the plot
    pp = PdfPages(outfil)
    scl = 1.0
    fig = plt.figure(figsize=(8.0 * scl, 5.0 * scl))

    plt.clf()
    gs = gridspec.GridSpec(5, 1)
    jet = cm = plt.get_cmap('jet')

    # Loop
    for qq in range(9):
        # Cartoon
        ax0 = plt.subplot(gs[0, 0])
        ax0.set_xlim(lrest)
        ax0.set_ylim(0., 1.)
        ax0.set_frame_on(False)
        ax0.axes.get_yaxis().set_visible(False)
        ax0.axes.get_xaxis().set_visible(False)

        # QSO
        ax0.scatter([1215.67], [yqso], marker='o', facecolor='blue', s=sqso)
        ax0.text(1215.67,
                 yqso + toff,
                 'Quasar (z=3)',
                 color='blue',
                 ha='center')

        # Redshifted light
        if qq > 0:
            light = np.linspace(1215.67, lrest[0], 20)
            ax0.scatter(light, [yqso] * len(light),
                        marker='_',
                        s=40,
                        cmap=cm,
                        c=1. / light)

        # Gas at QSO
        if qq > 1:
            ax0.scatter([1215.67], [yqso],
                        marker='o',
                        facecolor='none',
                        edgecolor='green',
                        s=sqso * 5)
            ax0.text(1215.67,
                     yqso - 1.7 * toff,
                     'HI Gas (z=3)',
                     color='green',
                     ha='center')

        # Spectrum
        ax = plt.subplot(gs[1:, 0])
        ax.set_xlim(lrest)
        #ax.set_ylim(ymnx)
        ax.set_ylabel('Relative Flux')
        ax.set_xlabel("Rest Wavelength")
        if qq < 3:
            tsty = 'k'
        else:
            tsty = 'b:'
        ax.plot(telfer.wavelength, telfer.flux, tsty)

        # Observer frame axis
        if qq > 0:
            ax2 = ax.twiny()
            ax2.set_xlim(ax.get_xlim())
            xtcks = ax.get_xticks()
            ax2.set_xticks(xtcks)
            ax2.set_xticklabels(tick_function(zem, xtcks))
            ax2.set_xlabel('Observed Wavelength (Angstroms)')

        # Absorption lines
        abslines = []
        if (qq > 2) and (qq != 8):
            # Lya at zem

            abslines.append(qsolya)
            if qq > 3:  # Lyb at zem
                abslines.append(qsolyb)
            # Gas at z=2.8
            if qq > 4:
                zadd = 2.8
                abslines += add_lines(ax0, zadd)
            # Gas at z=2.5
            if qq > 5:
                zadd = 2.5
                abslines += add_lines(ax0, zadd)
            if qq > 6:
                zadd = 2.2
                abslines += add_lines(ax0, zadd)
            #
            abs_model = ltav.voigt_from_abslines(telfer.wavelength * (1 + zem),
                                                 abslines)
            #ax.plot(telfer.wavelength, telfer.flux*abs_model.flux, 'k')
            ax.plot(telfer.wavelength, telfer.flux.value * abs_model.flux, 'k')

        # Final plot
        if qq == 8:
            nlin = 100
            dotwv = np.linspace(900, 1215., nlin)
            ax0.scatter(dotwv, [yqso] * nlin,
                        marker='o',
                        facecolor='none',
                        edgecolor='green',
                        s=sqso * 5)
            # Mock spectrum
            fN_model = FNModel.default_model()
            gdp = np.where(telfer.wavelength > 900. * u.AA)[0]
            mock_spec, HI_comps, misc = pyimock.mk_mock(
                telfer.wavelength[gdp] * (1 + zem),
                zem,
                fN_model,
                s2n=100.,
                fwhm=3,
                add_conti=False)
            ax.plot(telfer.wavelength[gdp],
                    telfer.flux[gdp].value * mock_spec.flux, 'k')

        # Layout and save
        plt.tight_layout(pad=0.2, h_pad=0.0, w_pad=0.4)
        plt.subplots_adjust(hspace=0)
        pp.savefig(bbox_inches='tight', transparent=True)
        plt.close()
    # Finish
    print('Writing {:s}'.format(outfil))
    pp.close()
    return mock_spec
Exemplo n.º 25
0
def hi_model(abssys,
             spec,
             lya_only=False,
             add_lls=False,
             ret_tau=False,
             ignore_abslines=False,
             bval=30 * u.km / u.s,
             **kwargs):
    """ Generate a model of the absorption from the absorption system
    on an input spectrum.

    Parameters
    ----------
    abssys : AbsSystem or list
      If list, must be a list of AbsSystem's
    spec : XSpectrum1D
    lya_only : bool, optional
      Only generate Lya
    ignore_abslines : bool, optional
      Ignore any existing abslines in the object
      NHI tag must be set
    add_lls : bool, optional
      Add Lyman continuum absorption
    bval : Quantity, optional
      Doppler parameter to use if abslines not adopted
    ret_tau : bool, optional
      Return only the optical depth (used for multiple systems)
    kwargs :
      Passed to voigt_from_abslines

    Returns
    -------
    vmodel : XSpectrum1D or ndarray
      Model spectrum with same wavelength as input spectrum
      Assumes a normalized flux
      Or optical depth array [used for multiple systems]
    lyman_lines : list
      List of AbsLine's that contributed to the model

    """
    from astropy.units import Quantity
    from linetools.spectra.xspectrum1d import XSpectrum1D
    from linetools.spectralline import AbsLine
    from linetools.analysis.voigt import voigt_from_abslines
    from linetools.analysis.absline import photo_cross
    # Input
    if isinstance(abssys, list):
        tau = None
        all_lines = []
        for iabssys in abssys:
            itau, ly_lines = hi_model(iabssys,
                                      spec,
                                      lya_only=lya_only,
                                      add_lls=add_lls,
                                      ignore_abslines=ignore_abslines,
                                      bval=bval,
                                      ret_tau=True,
                                      **kwargs)
            all_lines += ly_lines
            if tau is None:
                tau = itau
            else:
                tau += itau
        # Flux
        flux = np.exp(-1 * tau)
        vmodel = XSpectrum1D.from_tuple((spec.wavelength, flux))
        return vmodel, all_lines
    else:
        # Scan abs lines
        if not ignore_abslines:
            alines = []
        else:
            alines = abssys.list_of_abslines()
        lyman_lines = []
        lya_lines = []
        logNHIs = []
        # Scan alines
        for aline in alines:
            # Lya
            if aline.name == 'HI 1215':
                lya_lines.append(aline)
                logNHIs.append(np.log10(aline.attrib['N'].value))
            # Any HI
            if 'HI' in aline.name:
                lyman_lines.append(aline)
        if len(lya_lines) > 0:  # Use the lines
            # Check we have a DLA worth
            if np.log10(np.sum(10**np.array(logNHIs))) < abssys.NHI:
                raise ValueError(
                    "Total NHI of the Lya lines is less than NHI of the system!  Something is wrong.."
                )
        else:  # Generate one
            warnings.warn(
                "Generating the absorption lines from the system info, not abslines"
            )
            if lya_only:
                lya_line = AbsLine('HI 1215', z=abssys.zabs)
                lya_line.attrib['N'] = 10**abssys.NHI / u.cm**2
                lya_line.attrib['b'] = bval
                lyman_lines.append(lya_line)
            else:
                HIlines = LineList('HI')
                wrest = Quantity(HIlines._data['wrest'])
                for iwrest in wrest:
                    # On the spectrum?
                    if iwrest >= spec.wvmin / (1 + abssys.zabs):
                        lyman_line = AbsLine(iwrest,
                                             linelist=HIlines,
                                             z=abssys.zabs)
                        lyman_line.attrib['N'] = 10**abssys.NHI / u.cm**2
                        lyman_line.attrib['b'] = bval
                        lyman_lines.append(lyman_line)
        # tau for abs lines
        if len(lyman_lines) == 0:
            pdb.set_trace()
        tau_Lyman = voigt_from_abslines(spec.wavelength,
                                        lyman_lines,
                                        ret='tau',
                                        **kwargs)
        # LLS?
        if add_lls:
            wv_rest = spec.wavelength / (1 + abssys.zabs)
            energy = wv_rest.to(u.eV, equivalencies=u.spectral())
            # Get photo_cross and calculate tau
            tau_LL = (10.**abssys.NHI / u.cm**2) * photo_cross(1, 1, energy)
            # Kludge
            pix_LL = np.argmin(np.fabs(wv_rest - 911.3 * u.AA))
            pix_kludge = np.where((wv_rest > 911.3 * u.AA)
                                  & (wv_rest < 913.0 * u.AA))[0]
            tau_LL[pix_kludge] = tau_LL[pix_LL]
            tau_Lyman[pix_kludge] = 0.
            # Generate the spectrum
        else:
            tau_LL = 0.
        # Sum
        tau_tot = tau_LL + tau_Lyman
        if ret_tau:
            vmodel = tau_tot
        else:
            flux = np.exp(-1 * tau_tot)
            vmodel = XSpectrum1D.from_tuple((spec.wavelength, flux))
        # Return
        return vmodel, lyman_lines
abslin.attrib['N'] = 10**17.5 / u.cm**2
abslin.attrib['b'] = 20. * u.km / u.s

wave = np.linspace(3644, 3650, 100) * u.AA

vmodel2 = abslin.generate_voigt(wave=wave)

plt_line(vmodel2)

abslin2 = AbsLine('DI 1215')
abslin2.attrib['N'] = 10**13. / u.cm**2  # log N
abslin2.attrib['b'] = 15. * u.km / u.s
abslin2.attrib['z'] = 2.0

vmodel3 = lav.voigt_from_abslines(wave, [abslin, abslin2])

plt_line(vmodel3)

tau = lav.voigt_from_abslines(wave, abslin, ret='tau')

plt.plot(wave, tau, 'k-', drawstyle='steps-mid', lw=1.5)
plt.xlim(3642., 3652.)
plt.ylim(0., 15000.)
plt.ylabel('Optical Depth', fontsize=20.)
plt.xlabel('Wavelength', fontsize=20.)
plt.show()
plt.close()

from astropy.modeling import fitting
Exemplo n.º 27
0
def fig_lya_line(lw=1.5, csz=15.):
    """  Generate a DLA in optical depth and flux space
    Parameters
    ----------
    """
    llist = LineList('ISM')
    # Lya
    lya = AbsLine('HI 1215', z=0., llist=llist)

    # Wavelength
    wave = np.linspace(1100., 1310., 100000)*u.AA

    outfile = 'fig_lya_line.png'

    # Figure
    plt.figure(figsize=(8, 4))
    plt.clf()
    gs = gridspec.GridSpec(1, 2)


    # Tau plot
    ax1 = plt.subplot(gs[0])

    # Optical depth
    lya.attrib['N'] = 1e21 / u.cm**2
    lya.attrib['b'] = 20 * u.km/u.s
    tau = voigt_from_abslines(wave, lya, ret='tau')

    # Plot
    ax1.plot(wave, tau, 'g')

    # Axes
    ax1.set_xlim(1200., 1230.)
    ax1.set_ylim(1e-2, 5e7)
    ax1.set_yscale("log", nonposy='clip')
    ax1.set_ylabel(r'Optical Depth for $N_{\rm HI} = 10^{21} \, \rm cm^{-2}$')
    ax1.set_xlabel(r'Wavelength ($\AA$)')
    ax1.xaxis.set_major_locator(plt.MultipleLocator(10.))
    #
    set_spines(ax1, 2.)
    set_fontsize(ax1,csz)

    # Flux space
    ax2 = plt.subplot(gs[1])

    for logN in [19., 20., 21., 22.]:
        lya.attrib['N'] = 10**logN / u.cm**2
        spec = voigt_from_abslines(wave, lya)
        # Plot
        ax2.plot(spec.wavelength, spec.flux, label=r'$\log N_{\rm HI} = $'+'{:d}'.format(int(logN)))
    # Axes
    wvoff = 100.
    ax2.set_xlim(1215.-wvoff, 1215.+wvoff)
    ax2.set_ylim(-0.05, 1.1)
    #ax2.set_yscale("log", nonposy='clip')
    ax2.set_ylabel('Normalized Flux')
    ax2.set_xlabel(r'Wavelength ($\AA$)')
    ax2.xaxis.set_major_locator(plt.MultipleLocator(50.))
    #
    set_spines(ax2, 2.)
    set_fontsize(ax2,csz)
    legend = ax2.legend(loc='lower left', scatterpoints=1, borderpad=0.3,
                      handletextpad=0.3, fontsize='small', numpoints=1)

    # Write
    plt.tight_layout(pad=0.2,h_pad=0.,w_pad=0.1)
    plt.savefig(outfile, dpi=750)
    plt.close()
    print("Wrote {:s}".format(outfile))