Beispiel #1
0
    def _run_functions(self, *args, **kwargs):
        """
        Run fitting on the initialized models, fixing any parameters marked
        as such by the user, then update the displauyed parameters with fit
        values
        """
        temp_results = []
        for function in FUNCTIONS:
            # Centroid function requires a region argument, create one to pass
            if function == "Centroid":
                spectral_axis = self._spectrum1d.spectral_axis
                if self._spectrum1d.mask is None:
                    spec_region = SpectralRegion(spectral_axis[0],
                                                 spectral_axis[-1])
                else:
                    spec_region = self._spectrum1d.spectral_axis[np.where(
                        self._spectrum1d.mask == False)]
                    spec_region = SpectralRegion(spec_region[0],
                                                 spec_region[-1])
                temp_result = FUNCTIONS[function](self._spectrum1d,
                                                  spec_region)
            else:
                temp_result = FUNCTIONS[function](self._spectrum1d)

            temp_results.append({
                'function': function,
                'result': str(temp_result)
            })
            self.result_available = True

            self.results = []
            self.results = temp_results
Beispiel #2
0
def snr_spec(flux, wl, n):

    sample = len(wl)
    noise = n * np.asarray(random.sample(range(0, len(wl)), sample)) / len(wl)
    unc = StdDevUncertainty(noise)

    fluxn = [[] for i in range(len(wl))]
    i = 0
    for inc in unc:
        fluxn[i] = flux[i] + noise[i]
        i = i + 1

    spec1d = Spectrum1D(spectral_axis=wl * u.AA,
                        flux=fluxn * u.Jy,
                        uncertainty=unc)

    #ax = plt.subplots()[1]
    #ax.plot(spec1d.spectral_axis, spec1d.flux)
    #ax.set_xlim([3520,3550])

    sn1 = snr(spec1d, SpectralRegion(3070 * u.AA, 3090 * u.AA))
    sn = snr_derived(spec1d, SpectralRegion(3070 * u.AA, 3090 * u.AA))

    #print('SNR1: '+ str(snr(spec1d)), SpectralRegion(3500*u.AA, 3550*u.AA))
    print('SNR: ' + str(sn1))
    #print('SNR: '+ str(sn))
    #print('FWHM:'+str(fwhm(spec1d)))

    #0.042 = snr 50
    #

    try:
        return fluxn
    except:
        raise Exception('Check S/N function')
Beispiel #3
0
def line(spec,wave1,wave2):
    # finding the centorid and deriving guesses parameters
    centre=centroid(spec, SpectralRegion(wave1*u.AA, wave2*u.AA))  
    centre=float(centre/(1. * u.AA))
    FWHM=fwhm(spec) 
    FWHM=float(FWHM/(1. * u.AA))
    A=line_flux(spec, SpectralRegion(lamb1*u.AA, lamb2*u.AA))
    a=1* u.Unit('J cm-2 s-1 AA-1') 
    A=float(A/(1. * u.AA*a))
    # PARAMETERS
    return [centre,A,FWHM]
Beispiel #4
0
def EW(lamb,flux,name):

    flux = flux * u.Unit('J cm-2 s-1 AA-1') 
    #flux = flux * u.Unit('erg cm-2 s-1 AA-1') 
    lamb= lamb * u.AA 
    spec = Spectrum1D(spectral_axis=lamb, flux=flux) 
    #cont_norm_spec = spec / fit_generic_continuum(spec)(spec.spectral_axis) 
    cont_norm_spec = spec 
    print('-----------'+name+'------------')
#line A
    #EWa = equivalent_width(cont_norm_spec, regions=SpectralRegion(8493*u.AA, 8502*u.AA))
    #FWHMa = fwhm(cont_norm_spec, regions=SpectralRegion(8493*u.AA, 8502*u.AA))
    #print('EW A line: '+str(EWa))
#line B
    EWb = equivalent_width(cont_norm_spec, regions=SpectralRegion(lineBlims[0]*u.AA, lineBlims[1]*u.AA))
    print('EW B line: '+str(EWb))
#line C
    EWc = equivalent_width(cont_norm_spec, regions=SpectralRegion(lineClims[0]*u.AA, lineClims[1]*u.AA))
    print('EW C line: '+str(EWc))
#open log file 
    
    #nonlinear to metal-poor
    V_VHB = -2.0
    
    EWbc= (EWb+EWc)
    EWbc= float(EWbc/(1. * u.AA))
    
    EWp = (EWbc)**(-1.5) 
    
    #nonlinear to metal-poor
    #Wl = float(EWb / (1. * u.AA)) + float(EWc / (1. * u.AA)) + (0.64 * V_VHB)
    #FeH= -2.81 + 0.44*Wl
    # FeH constants to V-VHB
    
    a=-2.87
    b=0.195
    c=0.458
    d=-0.913
    e=0.0155
    
    #float all
    
    FeH = a + b * V_VHB + c * EWbc + d * EWp + e * EWbc * V_VHB 
     
    
    print('[Fe/H]: '+str(FeH))
    
    return [EWb,EWc,FeH]
def sky_centroids(sky_wave, smoothed_sky_flux, smoothed_sky_noise):
    """Returns centroids of skylines in the sky model.
    
    Parameters
    ----------
    sky_wave : tuple
        Wavelength array
    smoothed_sky_flux : tuple
        Smoothed flux array
    smoothed_sky_noise : tuple
        Smoothed noise array
        
    Returns
    -------
    sky_cents : tuple
        Skyline centroids
    """
    
    #Normalize sky model
    sky_norm_wave, sky_norm_flux, sky_norm_noise = continuum_normalize(np.min(sky_wave), np.max(sky_wave), smoothed_sky_flux, 
                                                                       sky_wave, smoothed_sky_noise)
    
    #Find centroids of skylines in model
    centroids = [7843, 7916, 7995.5, 8347, 8467, 8829.5, 8922, 9378, 9442, 9794]
    sky_bounds = [[7835, 7850], [7908, 7920], [7990, 8000], [8340, 8353], [8460, 8475], [8820, 8835], [8915, 8930], 
                      [9370, 9385], [9435, 9447], [9785, 9799]]

    sky = Spectrum1D(spectral_axis=sky_norm_wave*u.Angstrom, flux=sky_norm_flux*u.ct)
    regions_sky = []
    for i in range(len(sky_bounds)):
        regions_sky.append(SpectralRegion(sky_bounds[i][0]*u.Angstrom, sky_bounds[i][-1]*u.Angstrom))

    sky_cents = centroid(sky, regions_sky)
    
    return sky_cents
Beispiel #6
0
    def get_spectral_regions(self):
        """
        Retrieves glue subset objects from the spectrum viewer and converts
        them to `~specutils.SpectralRegion` objects.

        Returns
        -------
        spec_regs : dict
            Mapping from the names of the subsets to the subsets expressed
            as `specutils.SpectralRegion` objects.
        """
        regions = self.app.get_subsets_from_viewer("spectrum-viewer", subset_type="spectral")

        spec_regs = {}

        for name, reg in regions.items():
            # Use the region's unit. If N/A, use the reference_data's
            unit = reg.meta.get("spectral_axis_unit",
                                self.get_spectra(
                                    self.app.get_viewer("spectrum-viewer"
                                                        ).state.reference_data.label,
                                    apply_slider_redshift=False
                                    ).spectral_axis.unit
                                )

            spec_reg = SpectralRegion.from_center(reg.center.x * unit,
                                                  reg.width * unit)

            spec_regs[name] = spec_reg

        return spec_regs
Beispiel #7
0
def test_statistics_gui_roi_spectrum(specviz_gui):
    # Ensure that the test is run on an unmodified workspace instance
    workspace = new_workspace(specviz_gui)
    hub = Hub(workspace=workspace)

    # Make region of interest cutout, using default cutout at .3 from the
    # middle in either direction
    specviz_gui.current_workspace.current_plot_window.plot_widget._on_add_linear_region(
    )

    # Simulate cutout for truth data
    spectrum = extract_region(hub.plot_item._data_item.spectrum,
                              SpectralRegion(*hub.selected_region_bounds))

    # pull out stats dictionary
    stats_dict = specviz_gui.current_workspace._plugin_bars['Statistics'].stats

    # Generate truth comparisons
    truth_dict = {
        'mean': spectrum.flux.mean(),
        'median': np.median(spectrum.flux),
        'stddev': spectrum.flux.std(),
        'centroid': centroid(spectrum, region=None),
        'snr': "N/A",
        'fwhm': fwhm(spectrum),
        'ew': equivalent_width(spectrum),
        'total': line_flux(spectrum),
        'maxval': spectrum.flux.max(),
        'minval': spectrum.flux.min()
    }

    # compare!
    assert stats_dict == truth_dict

    workspace.close()
Beispiel #8
0
    def detect_spikes(self, candidate_threshold: float = 100, falloff_fraction: float = 0.75, check_offset: float = 3) \
            -> List[SpectralRegion]:

        # Candidates are threshold X mean(of whole spectrum) (simple algorithm for now - maybe look at localised mean)
        mean_flux = np.mean(self.flux)
        flux_threshold = candidate_threshold * mean_flux  # candidate_threshold must not have units or we get adu2
        candidates = np.where(self.flux >= flux_threshold)[0]
        spikes = []

        ix_last_flux_to_check = len(self.flux) - check_offset - 1
        for c_ix in candidates:
            if (c_ix + 1) in candidates:
                # If its neighbour is in the list then it can't be a spike
                pass
            elif check_offset <= c_ix <= ix_last_flux_to_check:
                # A spike must have a precipitous fall in non_ss_spectra either side
                # (by default, losing > 0.75 non_ss_spectra either side)
                previous_flux = self.flux[c_ix - check_offset]
                next_flux = self.flux[c_ix + check_offset]
                this_flux = self.flux[c_ix]
                falloff = this_flux - (
                    (this_flux - mean_flux) * falloff_fraction)
                if falloff > previous_flux and falloff > next_flux:
                    lambda_from = self.wavelength[c_ix - check_offset]
                    lambda_to = self.wavelength[c_ix + check_offset]
                    spikes.append(SpectralRegion(lambda_from, lambda_to))
        return spikes
Beispiel #9
0
def measure_ew_emission_line(model,
                             emline,
                             wave_margin=300,
                             redshift=0.0,
                             cont_low=5,
                             cont_upp=3,
                             cont_degree=2):
    """Measure the EW of an emission line after normalization."""
    # Decide the wavelength range
    wave_flag = ((model['wave'] >= emline['cen'] - wave_margin) &
                 (model['wave'] <= emline['cen'] + wave_margin))

    wave_use = model['wave'][wave_flag]
    flux_em = model['spec_em'][wave_flag]
    flux_ne = model['spec_ne'][wave_flag]

    # Normalize the spectrum, so the continuum level is 1.0
    flux_em_norm = sigma_clipping_continuum(wave_use,
                                            flux_em,
                                            low=5,
                                            upp=2,
                                            degree=cont_degree)

    flux_ne_norm = sigma_clipping_continuum(wave_use,
                                            flux_ne,
                                            low=2,
                                            upp=5,
                                            degree=cont_degree)

    # Form a Spectrum1D object
    ew_em = equivalent_width(
        Spectrum1D(spectral_axis=wave_use * u.AA,
                   flux=flux_em_norm * u.Unit('erg cm-2 s-1 AA-1')),
        regions=SpectralRegion(emline['low'] * u.AA * (1.0 + redshift),
                               emline['upp'] * u.AA * (1.0 + redshift)),
        continuum=1).value

    ew_ne = equivalent_width(
        Spectrum1D(spectral_axis=wave_use * u.AA,
                   flux=flux_ne_norm * u.Unit('erg cm-2 s-1 AA-1')),
        regions=SpectralRegion(emline['low'] * u.AA * (1.0 + redshift),
                               emline['upp'] * u.AA * (1.0 + redshift)),
        continuum=1).value

    return ew_ne - ew_em
Beispiel #10
0
    def getRegion(self, index=None):

        if index is not None:
            subset = self._v1d.state.layers[index].layer
            if hasattr(subset, 'subset_state') and isinstance(
                    subset.subset_state, RangeSubsetState):
                return SpectralRegion(subset.subset_state.lo * u.AA,
                                      subset.subset_state.hi * u.AA)
            else:
                return None
        else:
            return [
                SpectralRegion(l.layer.subset_state.lo * u.AA,
                               l.layer.subset_state.hi * u.AA)
                for l in self._v1d.state.layers
                if hasattr(l.layer, 'subset_state')
                and isinstance(l.layer.subset_state, RangeSubsetState)
            ]
def plot_feros_spectra(spectrum_path, outpath=None, xlim=None):
    hdul = fits.open(spectrum_path)

    d = hdul[0].data

    wav = d[0, 0]
    flx = d[3, 0]

    if isinstance(xlim, list):
        xmin = xlim[0]
        xmax = xlim[1]
        sel = (wav > xmin) & (wav < xmax)

        wav = wav[sel]
        flx = flx[sel]

    spec = Spectrum1D(spectral_axis=wav * u.AA,
                      flux=flx * u.dimensionless_unscaled)

    f, ax = plt.subplots()
    ax.plot(wav, flx, c='k', zorder=3)

    if isinstance(xlim, list):
        exclude_regions = []
        if xmin < 6709.2 and xmax > 6710.2:
            exclude_regions.append(SpectralRegion(6709.2 * u.AA,
                                                  6710.2 * u.AA))
        if xmin < 6679 and xmax > 6681:
            exclude_regions.append(SpectralRegion(6679 * u.AA, 6681 * u.AA))

        cont_flx = fit_generic_continuum(
            spec, exclude_regions=exclude_regions)(spec.spectral_axis)
        ax.plot(wav, cont_flx, c='r', zorder=2)

    ax.set_xlabel('wavelength [angstrom]')
    ax.set_ylabel('relative flux')

    if isinstance(xlim, list):
        ax.set_xlim(xlim)

    format_ax(ax)
    savefig(f, outpath)
Beispiel #12
0
    def _calculate_statistics(self, *args, **kwargs):
        """
        Run the line analysis functions on the selected data/subset and
        display the results.
        """
        if self.selected_spectrum == "":
            self.result_available = False
            return

        self._spectrum1d = self.app.get_data_from_viewer(
            "spectrum-viewer", data_label=self.selected_spectrum)

        if self.selected_subset != "Entire Spectrum":
            mask = self.app.get_data_from_viewer(
                "spectrum-viewer", data_label=self.selected_subset).mask
            self._spectrum1d.mask = mask

        temp_results = []
        for function in FUNCTIONS:
            # Centroid function requires a region argument, create one to pass
            if function == "Centroid":
                spectral_axis = self._spectrum1d.spectral_axis
                if self._spectrum1d.mask is None:
                    spec_region = SpectralRegion(spectral_axis[0],
                                                 spectral_axis[-1])
                else:
                    spec_region = self._spectrum1d.spectral_axis[np.where(
                        self._spectrum1d.mask == 0)]
                    spec_region = SpectralRegion(spec_region[0],
                                                 spec_region[-1])
                temp_result = FUNCTIONS[function](self._spectrum1d,
                                                  spec_region)
            else:
                temp_result = FUNCTIONS[function](self._spectrum1d)

            temp_results.append({
                'function': function,
                'result': str(temp_result)
            })

        self.results = temp_results
        self.result_available = True
Beispiel #13
0
 def _on_subset_selected(self, event):
     # If "None" selected, reset based on bounds of selected data
     if self.selected_subset == "None":
         cube = self._selected_data.get_object(cls=SpectralCube)
         self.spectral_min = cube.spectral_axis[0].value
         self.spectral_max = cube.spectral_axis[-1].value
     else:
         spec_sub = self._spectral_subsets[self.selected_subset]
         unit = u.Unit(self.spectral_unit)
         spec_reg = SpectralRegion.from_center(spec_sub.center.x * unit,
                                               spec_sub.width * unit)
         self.spectral_min = spec_reg.lower.value
         self.spectral_max = spec_reg.upper.value
Beispiel #14
0
 def _on_subset_selected(self, event):
     # If "None" selected, reset based on bounds of selected data
     if self.selected_subset == "None":
         self._window = None
         self.spectral_min = self._spectrum1d.spectral_axis[0].value
         self.spectral_max = self._spectrum1d.spectral_axis[-1].value
     else:
         spec_sub = self._spectral_subsets[self.selected_subset]
         unit = u.Unit(self.spectral_unit)
         spreg = SpectralRegion.from_center(spec_sub.center.x * unit,
                                            spec_sub.width * unit)
         self._window = (spreg.lower, spreg.upper)
         self.spectral_min = spreg.lower.value
         self.spectral_max = spreg.upper.value
Beispiel #15
0
    def findlines(self):
        '''
		Returns arrays with wavelength positions of absorption and emission lines.
		'''

        wavelength = self.wavelength
        flux = self.flux

        spectrum = Spectrum1D(flux=flux * u.Jy,
                              spectral_axis=wavelength * u.Angstrom)
        noise_region = SpectralRegion(3000 * u.Angstrom, 10000 * u.Angstrom)
        spectrum = noise_region_uncertainty(spectrum, noise_region)

        lines = find_lines_threshold(spectrum, noise_factor=4)

        emit = lines['line_type'] == 'emission'
        absorb = lines['line_type'] == 'absorption'

        emission_lines = lines['line_center'][emit]

        try:
            emission_lines_arr = np.zeros(len(emission_lines))
        except TypeError:
            print('no emission lines!')
            emission_lines_arr = None
            emission_lines = None

        if emission_lines is not None:
            for i in range(len(emission_lines)):
                emission_lines_arr[i] = emission_lines.data[i]

        absorption_lines = ['line_type'] == 'absorption'

        try:
            absorption_lines_arr = np.zeros(len(absorption_lines))
        except TypeError:
            print('no absorption lines!')
            absorption_lines_arr = None
            absorption_lines = None

        if absorption_lines is not None:
            for j in range(len(absorption_lines)):
                absorption_lines_arr[j] = absorption_lines.data[j]

        self.emit = emission_lines_arr
        self.absorb = absorption_lines_arr

        return (emission_lines_arr, absorption_lines_arr)
Beispiel #16
0
 def _calc_EW(self, wavelengths, flux, continuum):
     """
     Generic function to calculate (using SpecUtils) the Equivalent width of a line
     requires: Wavelengths (assumed to be in nm)
               Flux (assumed to be in photons)
               Continuum (assumed to be in photons)
     The equivalent width will be measured on the normalized spectrum (flux/continuum)
     output: Equivalent_Width (Quantity)
     """
     norm_spec = (flux / continuum) * u.photon
     norm_spec_wave = wavelengths * u.nanometer
     not_nan = ~np.isnan(norm_spec)
     spec = Spectrum1D(spectral_axis=norm_spec_wave[not_nan][::-1],
                       flux=norm_spec[not_nan][::-1])
     spec_region = SpectralRegion(
         np.min(wavelengths) * u.nm,
         np.max(wavelengths) * u.nm)
     return equivalent_width(spec, regions=spec_region)
Beispiel #17
0
    def get_spectral_regions(self):
        """
        Retrieves glue subset objects from the spectrum viewer and converts
        them to `~specutils.SpectralRegion` objects.

        Returns
        -------
        spec_regs : dict
            Mapping from the names of the subsets to the subsets expressed
            as `specutils.SpectralRegion` objects.
        """
        regions = self.app.get_subsets_from_viewer('spectrum-viewer')

        spec_regs = {}

        for name, reg in regions.items():
            unit = reg.meta.get('spectral_axis_unit', u.Unit('Angstrom'))
            spec_reg = SpectralRegion.from_center(reg.center.x * unit,
                                                  reg.width * unit)

            spec_regs[name] = spec_reg

        return spec_regs
        #plt.figure()
        #plt.plot(heii_wave, heii_norm.flux)

        center = 6565  #4685
        lower = center - 10
        upper = center + 10
        plt.figure()
        plt.plot(new_wave, new_flux, 'b')
        plt.xlim(lower, upper)
        peak = new_wave[(new_wave < upper) & (new_wave > lower)][np.argmax(
            new_flux[(new_wave < upper) & (new_wave > lower)])]
        print(
            peak,
            equivalent_width(new_spec,
                             regions=SpectralRegion(lower * u.AA,
                                                    upper * u.AA)))

#
#        center = 4686
#        lower = center - 10
#        upper =  center + 10
#        plt.figure(gal)
#        plt.plot(heii_wave,heii_norm.flux,'b')
#        plt.xlim(lower,upper)
#        #plt.ylim(0,3)
#        print(heii_wave[np.argmax(heii_flux)],
#                        equivalent_width(heii_norm, regions=SpectralRegion(lower*u.AA, upper*u.AA)))

#from spectres import spectres
#x = spectres(wave, new_wave, flux)
#print (x)
Beispiel #19
0
	def gaussian_fit(self,spectrum,submin,submax,star_name):	
		

		#noise_region=SpectralRegion(2.26*u.um,2.3*u.um)
		#spectrum=noise_region_uncertainty(spectrum,noise_region)
		#lines = find_lines_threshold(spectrum, noise_factor=4)
		
		#print(lines[lines['line_type'] == 'emission'])
		#print(lines[lines['line_type'] == 'absorption'])
		
		#amp=0.00075
		#centre=2.1675
		
		#sub region defined from function parameters
		
		sub_region=SpectralRegion(submin*u.um,submax*u.um)
		
		#spectrum extracted from subregion
		
		sub_spectrum=extract_region(spectrum,sub_region)
		
		#continuum fitted
		
		g1_fit=fit_generic_continuum(spectrum)
		
		y_continuum_fitted=g1_fit(sub_spectrum.spectral_axis)
		
		#continuum fit plotted with subregion spectrum
		
		plt.plot(sub_spectrum.spectral_axis,sub_spectrum.flux)
		plt.plot(sub_spectrum.spectral_axis,y_continuum_fitted)
		plt.title('Continuum Fitting')
		plt.grid(True)
		plt.show()
		
		#continuum substracted to show intensity
		
		sub_spectrum=sub_spectrum-y_continuum_fitted
		
		#initial gaussian fitted to estimate parameters for more accurate fitting
		
		estimates=estimate_line_parameters(sub_spectrum,models.Gaussian1D())
		
		#new gauss_axis variable created for a smooth fit
		
		gauss_axis=np.linspace(min(sub_spectrum.spectral_axis),max(sub_spectrum.spectral_axis),2000)
		
		#gaussian fit from previous estimates produced
		
		g_init=estimates
		
		g_fit=fit_lines(sub_spectrum,g_init)
		
		y_fit=g_fit(gauss_axis)
		
		#fit plotted
		
		plt.plot(sub_spectrum.spectral_axis,sub_spectrum.flux)
		plt.plot(gauss_axis,y_fit)
		
		#linestrength found
		
		strength=(max(y_fit))
		
		#f=open('brackett_strengths.txt','a')
		#f.write(star_name + ' - '+ str(strength) + 'Jy') 
		#f.close()
		
		plt.title('Single fit peak')
		plt.grid(True)
		plt.legend('Original Spectrum','Specutils Fit Result')
		
		plt.show()
Beispiel #20
0
###input values to integrate EW through
input_list = []
input_list.append(input('Ha wavelengths:'))
input_list.append(input('HeI2 wavelengths:'))
input_list.append(input('HeI3 wavelengths:'))
input_list.append(input('FeII2 wavelengths:'))


ew_list = []
cont_lst = []
##iterate through each observation to calculate Intensity.
for cont,spec in zip(cont_list,data):
    ew_iter = []
    cont_iter = []
    for inp ,region in zip(input_list,region_list):
        cont_iter.append(extract_region(cont, SpectralRegion(region[0] * u.AA, region[1] * u.AA)).flux)
        ew_iter.append(equivalent_width(spec, regions=SpectralRegion(int(inp.split(' ')[0]) * u.AA, int(inp.split(' ')[1]) * u.AA), continuum=extract_region(cont, SpectralRegion(region[0] * u.AA, region[1] * u.AA)).flux))
    ew_list.append(ew_iter)
    cont_lst.append(cont_iter)


ew1 = []
ew2 = []
ew3 = []
ew4 = []
for i in ew_list:
    ew1.append(np.mean(np.array(i[0])))
    ew2.append(np.mean(np.array(i[1])))
    ew3.append(np.mean(np.array(i[2])))
    ew4.append(np.mean(np.array(i[3])))
Beispiel #21
0
 def spectral_region_over(cls, lambda_from: float, lambda_to: float, units: str = "Angstrom") \
         -> SpectralRegion:
     return SpectralRegion(Quantity(lambda_from, units),
                           Quantity(lambda_to, units))
Beispiel #22
0
    def __init__(self,
                 spectrumIn,
                 wline,
                 band,
                 polyOrder=1,
                 widthFactor=4.,
                 verbose=0):
        # =======================================================================
        # Initial check in spectral_axis
        # =======================================================================
        if not (isinstance(spectrumIn.spectral_axis, u.Quantity)
                and isinstance(spectrumIn.flux, u.Quantity)):
            raise ValueError("Spectral axis must be a `Quantity` object.")
            if not spectrumIn.spectral_axis.unit == u.um:
                raise ValueError("Spectral axis is not in units of microns")

        self.polyOrder = polyOrder
        resv = self.get_spec_resolution(int(band[1]),
                                        np.array(wline, dtype=float))
        # =======================================================================
        # Convert delta velocity to delta lambda in microns with astropy units equivalencies
        # =======================================================================
        # c_kms = const.c.to('km/s')
        # fwhmum = (resv * u.kilometer/ u.s / c_kms) * wline
        rest_wline = wline * u.um
        fwhmum_q = (resv * u.km / u.s).to(
            u.um, equivalencies=u.doppler_optical(rest_wline)) - rest_wline
        fwhmum = fwhmum_q.value
        fwhm_to_sigma = 1. / (8 * np.log(2))**0.5
        lineWidthEstimate = fwhmum * fwhm_to_sigma
        wmin, wmax = wline[0] - (widthFactor *
                                 fwhmum), wline[-1] + (widthFactor * fwhmum)
        if verbose:
            print("wline, wmin, wmax, resv, fwhmum, lineWidthEstimate: ",
                  wline, wmin, wmax, resv, fwhmum, lineWidthEstimate)

        self.wmin = wmin
        self.wmax = wmax
        self.spectrumIn = spectrumIn
        # =======================================================================
        # mask non finite elements
        # =======================================================================
        spectrum = self.__finite(spectrumIn, verbose=verbose)
        self.spectrum = spectrum

        wunit = self.spectrum.spectral_axis.unit
        region = SpectralRegion(self.wmin * wunit, self.wmax * wunit)
        spectrum_region = extract_region(self.spectrum, region)

        # =======================================================================
        # Compute peak flux estimates for model parameters starting values in the region
        # =======================================================================
        peakFluxEstimate = []
        for wsline in wline:
            wave = spectrum_region.spectral_axis.value  #just the ndarray and not Quantity
            flux = spectrum_region.flux.value
            wdist = np.abs(wsline - wave)
            if verbose: print(wsline, min(wdist), max(wdist))
            indexLine = np.where(wdist == min(wdist))[0][0]
            if verbose: print("indexLine= {}".format(indexLine))
            peakEstimate = np.mean(flux[indexLine - 1:indexLine + 1])
            if verbose:
                print('Estimates for peak init {}'.format(peakEstimate))
            cont_sample = np.concatenate((flux[:5], flux[-5:]), axis=None)
            continuumEstimate = np.median(
                np.concatenate((flux[:5], flux[-5:]), axis=None))
            peakFluxEstimate = np.append(peakFluxEstimate,
                                         peakEstimate - continuumEstimate)
            if verbose:
                print('Estimates for peak & continuum {}, {}'.format(
                    peakFluxEstimate, continuumEstimate))

        # =======================================================================
        # Construct model compound (branching off lines+continuum or continuum)
        # =======================================================================

        try:
            lineModel_init = models.Polynomial1D(self.polyOrder,
                                                 c0=continuumEstimate,
                                                 name='cont')
            for xi in range(len(wline)):
                lineModel_init += models.Gaussian1D(
                    amplitude=peakFluxEstimate[xi],
                    mean=wline[xi],
                    stddev=lineWidthEstimate[xi],
                    name='g{}'.format(xi + 1))
            fitter = LevMarLSQFitter()
            lineModel = fit_lines(self.spectrum,
                                  lineModel_init,
                                  fitter=fitter,
                                  window=region)
            fitResult = lineModel(self.spectrum.spectral_axis)
            findLine = 1

            self.flux = []
            self.sigma = []

            for idx in range(len(wline)):
                #momentarily taking advantage of astropy units for conversion
                line_amp = (lineModel.unitless_model[idx + 1].amplitude.value *
                            u.Jy).to(u.Watt / u.m**2 / u.Hz)
                line_sig = (lineModel.unitless_model[idx + 1].stddev.value *
                            u.um).to(u.Hz, equivalencies=u.spectral())
                self.flux = np.append(self.flux, (line_amp * line_sig *
                                                  np.sqrt(2. * np.pi)).value)
                self.sigma = np.append(self.sigma, line_sig.value)
        except:
            if verbose: print('Exception')
            lineModel_init = models.Polynomial1D(self.polyOrder,
                                                 c0=continuumEstimate,
                                                 name='cont')
            fitter = LevMarLSQFitter()
            lineModel = fit_lines(
                self.spectrum, lineModel_init, fitter=fitter, window=region
            )  #the problem is narrow window where the contribution of the continuum sample is small
            fitResult = lineModel(self.spectrum.spectral_axis)
            findLine = 0
        self.model = lineModel
        self.fitResult = fitResult
        self.findLine = findLine
        self.fitter = fitter
        # =======================================================================
        # Preserve continuum Polynomial model
        # =======================================================================
        # there are two types of models, those that are based on
        # `~astropy.modeling.models.PolynomialModel` and therefore
        # require the ``degree`` parameter when instantiating the
        # class , and "everything else" that does not require an
        # "extra" parameter for class instantiation.
        compound_model = lineModel.n_submodels > 1
        if compound_model:
            self.continuumModel = lineModel.unitless_model[0]
        else:
            self.continuumModel = lineModel.unitless_model
        if findLine:
            self.continuum = []
            self.peak = []
            self.centre = []
            self.sigma = []
            self.fwhm = []
            self.chiSquared = (self.fitter.fit_info['fvec']**2).sum() / (
                len(self.fitter.fit_info['fvec']) -
                len(self.fitter.fit_info['param_cov'].data))
            self.stddev = np.sqrt(
                np.diag(fitter.fit_info['cov_x']
                        ))  #standard deviations pertaining to all parameters.
            params_idx = [
                int(param.split('_', -1)[-1])
                for param in self.model.param_names
            ]
            self.fluxError = []
            self.fluxErrorRelative = []
            for idx in range(len(wline)):
                self.continuum = np.append(
                    self.continuum,
                    self.continuumModel(
                        lineModel.unitless_model[idx + 1].mean.value))
                self.peak = np.append(
                    self.peak,
                    lineModel.unitless_model[idx + 1].amplitude.value)
                self.centre = np.append(
                    self.centre, lineModel.unitless_model[idx + 1].mean.value)
                self.sigma = np.append(
                    self.sigma, lineModel.unitless_model[idx + 1].stddev.value)
                self.fwhm = np.append(self.fwhm, self.sigma / fwhm_to_sigma)
                line_amp = (lineModel.unitless_model[idx + 1].amplitude.value *
                            u.Jy).to(u.Watt / u.m**2 / u.Hz)
                line_sig = (lineModel.unitless_model[idx + 1].stddev.value *
                            u.um).to(u.Hz, equivalencies=u.spectral())
                param_idx = [
                    i for i, value in enumerate(params_idx)
                    if value == (idx + 1)
                ]
                self.fluxErrorRelative = np.append(
                    self.fluxErrorRelative,
                    np.sqrt(
                        np.sum((self.stddev / self.model.parameters)[np.array(
                            [param_idx])][np.array([0, -1])]**2.)))
            self.fluxError = self.fluxErrorRelative * self.flux
            self.width = self.fwhm
        else:
            self.continuum = np.array(
                [np.median(flux) for i in range(len(wline))])
            self.flux = self.peak = self.sigma = self.fwhm = self.width = np.array(
                [0. for i in range(len(wline))])
            self.centre = wline
            if verbose:
                print('Line Not Detected. Continuum: {}'.format(
                    self.continuum))
        self.line_spec = self.get_line_spec()
        self.chiSquared = (self.fitter.fit_info['fvec']**2).sum() / (
            len(self.fitter.fit_info['fvec']) -
            len(self.fitter.fit_info['param_cov'].data))

        return
Beispiel #23
0
import numpy as np
from copy import copy
from datetime import datetime
from typing import List, Tuple, Union
from astropy.units import si
from astropy.modeling import CompoundModel
from astropy.modeling.models import Gaussian1D, Polynomial1D
from astropy.modeling.fitting import LevMarLSQFitter
from specutils import SpectralRegion, Spectrum1D
from specutils.fitting.continuum import fit_generic_continuum
from spectroscopy import Spectrum1DEx, fit_utilities

_b_e_exclusion_regions = SpectralRegion([(3900, 4150), (4300, 4700),
                                         (4800, 4950), (4960, 5080)] * si.AA)

_r_e_exclusion_regions = SpectralRegion([(5900, 6100), (6450, 6750)] * si.AA)


def fit(spectrum: Spectrum1DEx, key: str = None) -> List[CompoundModel]:
    """
    This is the switchboard method for the spectral fitting.
    If it can find a specific method to do the fitting it'll call that, otherwise it falls back on to generic methods.
    """
    this_module = __import__(__name__)
    method = f"fit_{key if key is not None else spectrum.name}"
    if hasattr(this_module, method):
        func = getattr(this_module, method)
    elif spectrum.is_blue:
        func = fit_blue_arm_spectrum
    else:
        func = fit_red_arm_spectrum
Beispiel #24
0
def line_fit(spec,
             spec_err,
             wave_obj,
             dwave=10. * u.AA,
             dwave_cont=100. * u.AA,
             sigmamax=14. * u.AA):
    '''
    Function to fit a 1D gaussian to a HETDEX spectrum from get_spec.py

    Parameters
    ----------
    spec
        1D spectrum from a row in the table provided by get_spec.py.
        Will assume unit of 10**-17*u.Unit('erg cm-2 s-1 AA-1') if no units
        are provided.
    spec_err
        1D spectral uncertainty from table provided by get_spec.py.
        Will assume unit of 10**-17*u.Unit('erg cm-2 s-1 AA-1') if no units
        are provided.
    wave_obj
        wavelength you want to fit, an astropy quantity
    dwave
        spectral region above and below wave_obj to fit a line, an astropy quantity.
        Default is 10.*u.AA
    dwave_cont
        spectral region to fit continuum. Default is +/- 100.*u.AA
    sigmamax
        Maximum linewidth (this is sigma/stdev of the gaussian fit) to allow
        for a fit. Assumes unit of u.AA if not given

    Returns
    -------

    '''

    try:
        spectrum = Spectrum1D(flux=spec,
                              spectral_axis=(2.0 * np.arange(1036) + 3470.) *
                              u.AA,
                              uncertainty=StdDevUncertainty(spec_err),
                              velocity_convention=None)
    except ValueError:
        spectrum = Spectrum1D(
            flux=spec * 10**-17 * u.Unit('erg cm-2 s-1 AA-1'),
            spectral_axis=(2.0 * np.arange(1036) + 3470.) * u.AA,
            uncertainty=StdDevUncertainty(spec_err * 10**-17 *
                                          u.Unit('erg cm-2 s-1 AA-1')),
            velocity_convention=None)

    # measure continuum over 2*dwave_cont wide window first:
    cont_region = SpectralRegion((wave_obj - dwave_cont),
                                 (wave_obj + dwave_cont))
    cont_spectrum = extract_region(spectrum, cont_region)
    cont = np.median(cont_spectrum.flux)

    if np.isnan(cont):
        #set continuum if its NaN
        print('Continuum fit is NaN. Setting to 0.0')
        cont = 0.0 * cont_spectrum.unit

    # now get region to fit the continuum subtracted line

    sub_region = SpectralRegion((wave_obj - dwave), (wave_obj + dwave))
    sub_spectrum = extract_region(spectrum, sub_region)

    try:
        line_param = estimate_line_parameters(sub_spectrum - cont,
                                              models.Gaussian1D())
    except:
        return None

    if np.isnan(line_param.amplitude.value):
        print('Line fit yields NaN result. Exiting.')
        return None

    try:
        sigma = np.minimum(line_param.stddev, sigmamax)
    except ValueError:
        sigma = np.minimum(line_param.stddev, sigmamax * u.AA)

    if np.isnan(sigma):
        sigma = sigmamax

    g_init = models.Gaussian1D(amplitude=line_param.amplitude,
                               mean=line_param.mean,
                               stddev=sigma)

    #    lineregion = SpectralRegion((wave_obj-2*sigma), (wave_obj+2*sigma))
    #    cont = fit_generic_continuum(sub_spectrum, exclude_regions=lineregion,
    #                                 model=models.Linear1D(slope=0))

    #r1 = SpectralRegion((wave_obj-dwave), (wave_obj-2*sigma))
    #r2 = SpectralRegion((wave_obj+2*sigma), (wave_obj+dwave))
    #fitcontregion = r1 + r2

    #fit_cont_spectrum = extract_region(sub_spectrum, fitcontregion)
    #cont = np.mean(np.hstack([fit_cont_spectrum[0].flux, fit_cont_spectrum[1].flux]))

    #contspec = cont(sub_spectrum.spectral_axis)

    g_fit = fit_lines(sub_spectrum - cont, g_init)

    x = np.arange(wave_obj.value - dwave.value, wave_obj.value + dwave.value,
                  0.5) * u.AA
    y_fit = g_fit(x)

    line_flux_model = np.sum(y_fit * 0.5 * u.AA)

    chi2 = calc_chi2(sub_spectrum - cont, g_fit)

    sn = np.sum(np.array(sub_spectrum.flux)) / np.sqrt(
        np.sum(sub_spectrum.uncertainty.array**2))

    line_flux_data = line_flux(sub_spectrum - cont).to(u.erg * u.cm**-2 *
                                                       u.s**-1)

    line_flux_data_err = np.sqrt(np.sum(sub_spectrum.uncertainty.array**2))

    #fitted_region = SpectralRegion((line_param.mean - 2*sigma),
    #                               (line_param.mean + 2*sigma))

    #fitted_spectrum = extract_region(spectrum, fitted_region)

    #line_param = estimate_line_parameters(fitted_spectrum, models.Gaussian1D())

    #sn = np.sum(np.array(fitted_spectrum.flux)) / np.sqrt(np.sum(
    #    fitted_spectrum.uncertainty.array**2))

    #line_flux_data = line_flux(fitted_spectrum).to(u.erg * u.cm**-2 * u.s**-1)

    #line_flux_data_err = np.sqrt(np.sum(fitted_spectrum.uncertainty.array**2))

    return line_param, sn, chi2, sigma, line_flux_data, line_flux_model, line_flux_data_err, g_fit, cont
Beispiel #25
0
#MASK lines continum and SNR 


#define mask SNR 
mask_CATb = (x > regions_ex[0]) & (x < regions_ex[1])
mask_CATc = (x > regions_ex[2]) & (x < regions_ex[3])

mask_SNR = [any(tup) for tup in zip(mask_CATb, mask_CATc)]
Imask_SNR = np.invert(mask_SNR)


#corr offset
Corr_rv= rv1(LINES[list(LINES.keys())[1]],float(lineBcentre/(1. * u.AA)))


Che_model=fit_generic_continuum(spec, exclude_regions=[SpectralRegion(corr_mask(regions_ex[0],Corr_rv)*u.AA, corr_mask(regions_ex[1],Corr_rv)*u.AA), 
                                                          SpectralRegion(corr_mask(regions_ex[2],Corr_rv)*u.AA, corr_mask(regions_ex[3],Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8409,Corr_rv)*u.AA, corr_mask(8415,Corr_rv)*u.AA), 
                                                          SpectralRegion(corr_mask(8415,Corr_rv)*u.AA, corr_mask(8422,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8422,Corr_rv)*u.AA, corr_mask(8428,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8431,Corr_rv)*u.AA, corr_mask(8442,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8465,Corr_rv)*u.AA, corr_mask(8471,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8579,Corr_rv)*u.AA, corr_mask(8585,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8595,Corr_rv)*u.AA, corr_mask(8600,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8610,Corr_rv)*u.AA, corr_mask(8623,Corr_rv)*u.AA),
                                                          ])


#Che_model=fit_generic_continuum(spec, exclude_regions=[SpectralRegion(regions_ex[0]*u.AA, regions_ex[1]*u.AA), 
#                                                          SpectralRegion(regions_ex[2]*u.AA, regions_ex[3]*u.AA)])
Beispiel #26
0
if __name__ == "__main__":
    wline = [185.999]
    band = 'R1'
    order = int(band[1])
    np.random.seed(0)
    x = np.linspace(180., 190., 100)
    y = 3 * np.exp(-0.5 * (x - 185.999)**2 / 0.1**2)
    y += np.random.normal(0., 0.2, x.shape)

    y_continuum = 3.2 * np.exp(-0.5 * (x - 5.6)**2 / 4.8**2)
    y += y_continuum

    #create spectrum to fit
    spectrum = Spectrum1D(flux=y * u.Jy, spectral_axis=x * u.um)
    noise_region = SpectralRegion(180. * u.um, 184. * u.um)
    spectrum = noise_region_uncertainty(spectrum, noise_region)

    #line_region = [(185.52059807*u.um, 186.47740193*u.um)]
    g1_fit = fit_generic_continuum(spectrum, model=models.Polynomial1D(1))
    y_continuum_fitted = g1_fit(x * u.um)

    plt.plot(x, y, label='spectrum')
    plt.errorbar(x, y, yerr=spectrum.uncertainty.array, color='b')
    plt.plot(x, y_continuum_fitted, label='cont_0')
    plt.title('Continuum+line Fitting')
    plt.grid(True)

    line = LineFitterMult(spectrum,
                          wline,
                          band,
def get_toi837_li_equivalent_width():

    spectrum_path = '../data/spectra/TOI-837_FEROS.fits'
    plotpath = '../results/TOI_837/feros_spectrum_get_li_equivalent_width.png'

    #
    # fit out the continuum to get the continuum normalized flux, over the
    # window of 6670 angstrom to 6713 angstrom.
    #
    xlim = [6670, 6713]

    hdul = fits.open(spectrum_path)
    d = hdul[0].data
    wav = d[0, 0]
    flx = d[3, 0]

    if isinstance(xlim, list):
        xmin = xlim[0]
        xmax = xlim[1]
        sel = (wav > xmin) & (wav < xmax)

        wav = wav[sel]
        flx = flx[sel]

    spec = Spectrum1D(spectral_axis=wav * u.AA,
                      flux=flx * u.dimensionless_unscaled)

    if isinstance(xlim, list):
        exclude_regions = []
        if xmin < 6709.2 and xmax > 6710.2:
            exclude_regions.append(SpectralRegion(6709.2 * u.AA,
                                                  6710.2 * u.AA))
        if xmin < 6679 and xmax > 6681:
            exclude_regions.append(SpectralRegion(6679 * u.AA, 6681 * u.AA))

    cont_flx = (fit_generic_continuum(spec, exclude_regions=exclude_regions)(
        spec.spectral_axis))

    cont_norm_spec = spec / cont_flx

    #
    # to fit gaussians, look at 1-flux.
    #
    full_spec = Spectrum1D(spectral_axis=cont_norm_spec.wavelength,
                           flux=(1 - cont_norm_spec.flux))

    #
    # get the Li EW
    #
    region = SpectralRegion(6708.5 * u.AA, 6711.5 * u.AA)
    li_equiv_width = equivalent_width(cont_norm_spec, regions=region)
    li_centroid = centroid(full_spec, region)

    #
    # fit a gaussian too, and get ITS equiv width
    # https://specutils.readthedocs.io/en/stable/fitting.html
    #
    g_init = models.Gaussian1D(amplitude=0.2 * u.dimensionless_unscaled,
                               mean=6709.7 * u.AA,
                               stddev=0.5 * u.AA)
    g_fit = fit_lines(full_spec, g_init, window=(region.lower, region.upper))
    y_fit = g_fit(full_spec.wavelength)

    fitted_spec = Spectrum1D(spectral_axis=full_spec.wavelength,
                             flux=(1 - y_fit) * u.dimensionless_unscaled)
    fitted_li_equiv_width = equivalent_width(fitted_spec, regions=region)

    #
    # print bestfit params
    #
    print(42 * '=')
    print('got Li equiv width of {}'.format(li_equiv_width))
    print('got fitted Li equiv width of {}'.format(fitted_li_equiv_width))
    print('got Li centroid of {}'.format(li_centroid))
    print('fit gaussian1d params are\n{}'.format(repr(g_fit)))
    print(42 * '=')

    #
    # plot the results
    #
    f, axs = plt.subplots(nrows=4, ncols=1, figsize=(6, 8))

    axs[0].plot(wav, flx, c='k', zorder=3)
    axs[0].plot(wav, cont_flx, c='r', zorder=2)

    axs[1].plot(cont_norm_spec.wavelength, cont_norm_spec.flux, c='k')

    axs[2].plot(cont_norm_spec.wavelength, cont_norm_spec.flux, c='k')

    axs[3].plot(full_spec.wavelength, full_spec.flux, c='k')
    axs[3].plot(full_spec.wavelength, y_fit, c='g')

    txt = ('gaussian1d\namplitude:{:.3f}\nmean:{:.3f}\nstd:{:.3f}\nEW:{:.3f}'.
           format(g_fit.amplitude.value, g_fit.mean.value, g_fit.stddev.value,
                  fitted_li_equiv_width))
    axs[3].text(0.95,
                0.95,
                txt,
                ha='right',
                va='top',
                transform=axs[3].transAxes,
                fontsize='xx-small')

    axs[0].set_ylabel('flux')
    axs[1].set_ylabel('contnorm flux')
    axs[2].set_ylabel('contnorm flux [zoom]')
    axs[3].set_ylabel('1 - (contnorm flux)')

    if isinstance(xlim, list):
        for ax in axs:
            ax.set_xlim(xlim)

    axs[2].set_xlim([6708.5, 6711.5])
    axs[3].set_xlim([6708.5, 6711.5])
    axs[-1].set_xlabel('wavelength [angstrom]')

    for ax in axs:
        format_ax(ax)
    outpath = '../results/TOI_837/toi837_li_equivalent_width_routine.png'
    savefig(f, outpath)
Beispiel #28
0
def EW(specname,name):

    lamb, flux= np.genfromtxt(specname, skip_header=1, unpack=True)

    flux = flux * u.Unit('J cm-2 s-1 AA-1') 
    #flux = flux * u.Unit('erg cm-2 s-1 AA-1') 
    lamb= lamb * u.AA 
    spec = Spectrum1D(spectral_axis=lamb, flux=flux) 
    # normalization is not so good 
    cont_norm_spec = spec / fit_generic_continuum(spec)(spec.spectral_axis) 

    print('-----------'+name+'------------')
#line A
    EWa = equivalent_width(cont_norm_spec, regions=SpectralRegion(8493*u.AA, 8502*u.AA))
    #FWHMa = fwhm(cont_norm_spec, regions=SpectralRegion(8493*u.AA, 8502*u.AA))
    print('EW A line: '+str(EWa))
#line B
    EWb = equivalent_width(cont_norm_spec, regions=SpectralRegion(8533*u.AA, 8551*u.AA))
    print('EW B line: '+str(EWb))
#line C
    EWc = equivalent_width(cont_norm_spec, regions=SpectralRegion(8655*u.AA, 8670*u.AA))
    print('EW C line: '+str(EWc))
#open log file 
    
    #nonlinear to metal-poor
    V_VHB = -2.0
    
    EWbc= (EWb+EWc)
    EWbc= float(EWbc/(1. * u.AA))
    
    EWp = (EWbc)**(-1.5) 
    
    #nonlinear to metal-poor
    #Wl = float(EWb / (1. * u.AA)) + float(EWc / (1. * u.AA)) + (0.64 * V_VHB)
    #FeH= -2.81 + 0.44*Wl
    # FeH constants to V-VHB
    
    a=-2.87
    b=0.195
    c=0.458
    d=-0.913
    e=0.0155
    
    #float all
    
    FeH = a + b * V_VHB + c * EWbc + d * EWp + e * EWbc * V_VHB 
    
    
    
    print('[Fe/H]: '+str(FeH))

    #change relampled spectrum to noise spectrum 
    LOG = open('./EWs/EWfile-'+name+'.txt', 'w')
    #LOG = open('./EWs/EWfileRE-'+name+'.txt', 'w')
    LOG.write('Log file of '+ name +' \n \n')
    LOG.write('Input Spectrum:   '+ specname +' \n \n')
    LOG.write('EW A line:             '+ str(EWa) +' \n') 
    LOG.write('EW B line:             '+ str(EWb) +' \n') 
    LOG.write('EW C line:             '+ str(EWc) +' \n') 
    LOG.write('[Fe/H]_CaT:             '+ str(FeH) +' \n') 

    
    f1 = plt.figure(figsize=(16,9))

    ax = f1.add_subplot(111)
    ax.plot(cont_norm_spec.spectral_axis, cont_norm_spec.flux)
    ax.set_xlim([8480,8690])
    ax.set_ylabel('Flux (J cm-2 s-1 AA-1)')
    ax.set_xlabel('Wavelength ( $\AA$ )')
    ax.axvspan(8498-float(EWa / (2. * u.AA))  , 8498+float(EWa / (2. * u.AA))   , alpha=0.2, color='red')
    ax.axvspan(8542-float(EWb / (2. * u.AA))  , 8542+float(EWb / (2. * u.AA))   , alpha=0.2, color='red')
    ax.axvspan(8662-float(EWc / (2. * u.AA))  , 8662+float(EWc / (2. * u.AA))   , alpha=0.2, color='red')
    
    #change relampled spectrum to noise spectrum 
    plt.savefig('./EWs/EW-figs/EW'+name+'.pdf')
Beispiel #29
0
input_list = []
input_list.append(input('NII wavelengths:'))
input_list.append(input('HeI1 wavelengths:'))
input_list.append(input('FeII1 wavelengths:'))
input_list.append(input('OI1 wavelengths:'))

ew_list = []
cont_lst = []
##iterate through each observation to calculate Intensity.
for cont, spec in zip(cont_list, data):
    ew_iter = []
    cont_iter = []
    for inp, region in zip(input_list, region_list):
        cont_iter.append(
            extract_region(cont,
                           SpectralRegion(region[0] * u.AA,
                                          region[1] * u.AA)).flux)
        ew_iter.append(
            equivalent_width(spec,
                             regions=SpectralRegion(
                                 int(inp.split(' ')[0]) * u.AA,
                                 int(inp.split(' ')[1]) * u.AA),
                             continuum=extract_region(
                                 cont,
                                 SpectralRegion(region[0] * u.AA,
                                                region[1] * u.AA)).flux))
    ew_list.append(ew_iter)
    cont_lst.append(cont_iter)

ew1 = []
ew2 = []
ew3 = []
def centroid_offsets(targ_bounds, data_wave, data_flux, sky_cents):
    """Returns amount by which extracted skylines are offset from model and the nearest wavelength value to each.
    
    Parameters
    ----------
    targ_bounds : tuple
        List of tuples defining bounds of region around each skyline to examine
    data_wave : tuple
        Wavelength array
    data_flux : tuple
        Flux array
    sky_cents : tuple
        Skymodel centroids
        
    Returns
    -------
    nearest_waves : tuple
        Nearest wavelength value to centroid
    offsets : tuple
        Offset between data and skymodel
    """
    
    regions = SpectralRegion(targ_bounds[0][0]*u.Angstrom,targ_bounds[0][-1]*u.Angstrom)
    for i in range(1, len(targ_bounds)):
        regions += SpectralRegion(targ_bounds[i][0]*u.Angstrom, targ_bounds[i][-1]*u.Angstrom)

    #Normalize data
    targ_norm_wave, targ_norm_flux, targ_norm_noise = continuum_normalize(np.min(data_wave), np.max(data_wave), data_flux, 
                                                                          data_wave, np.zeros(len(data_flux)))
    
    
    #Find offsets
    target = Spectrum1D(spectral_axis=targ_norm_wave*u.Angstrom, flux=targ_norm_flux*u.ct)
    sub_spec = extract_region(target, regions)
    offsets = np.zeros(len(sky_cents))
    nearest_waves = np.zeros(len(sky_cents))
    for i, sub in enumerate(sub_spec):
        an_disp = sub.flux.max()
        an_ampl = sub.flux.min()
        an_mean = sub.spectral_axis[sub.flux.argmax()]
        nearest_waves[i] = an_mean.value
        an_stdv = np.sqrt(np.sum((sub.spectral_axis - an_mean)**2) / (len(sub.spectral_axis) - 1))

        plt.figure()
        plt.scatter(an_mean.value, an_disp.value, marker='o', color='#e41a1c', s=100, label='data')
        plt.scatter(sky_cents[i], an_disp.value, marker='o', color='k', s=100, label='archive')
        plt.vlines([an_mean.value - an_stdv.value, an_mean.value + an_stdv.value],
                    sub.flux.min().value, sub.flux.max().value,
                    color='#377eb8', ls='--', lw=2)
        g_init = ( models.Const1D(an_disp) +
                  models.Gaussian1D(amplitude=(an_ampl - an_disp),
                                mean=an_mean, stddev=an_stdv) )
        g_fit = fit_lines(sub, g_init)
        line_fit = g_fit(sub.spectral_axis)
        plt.plot(sub.spectral_axis, sub.flux, color='#e41a1c', lw=2)
        plt.plot(sub.spectral_axis, line_fit, color='#377eb8', lw=2)

        plt.axvline(an_mean.value, color='#e41a1c', ls='--', lw=2)
        plt.legend()
        offsets[i] = an_mean.value - sky_cents[i].value
        
    return nearest_waves, offsets