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]
Beispiel #5
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()
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 #7
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 #8
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 #9
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 #11
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 #12
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 #13
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)
        #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 #15
0
emission_wvln = emission['line_center']

#we can also get the index where they occur in if we want to look at the non
#Spectrum1D object
emisison_index = emission['line_center_index']


#Once we have the emission lines all taken care of we can then use this information
#to do some fitting and get an estimate of the line flux and start performing some 
#science


#to fit a gaussian using specutils we need to have a region over which to fit
#for this we can cut a region around the emission center and fit a gaussian to that
window = 20*u.angstrom

#here we cut a slice of the spectum to look
sub_region = SpectralRegion('emission center' - window, 'emission center' + window)
sub_spectrum = extract_region('centered flux', sub_region)

#then we can estimate the mean, amplitude and stddev for the gaussian using 
#estimate_line_parameter

param = estimate_line_parameters(sub_spectrum, models.Gaussian1D())

#now with these parameters in place we fit the data of the sub spectrum
gauss_fit = fit_lines(sub_spectrum, 
                      models.Gaussian1D(amplitude=param.amplitude,
                                        stddev=param.stddev
                                        mean=param.mean))
Beispiel #16
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 #17
0
mask_CATb = (x > regions_ex[2]) & (x < regions_ex[3])
mask_CATc = (x > regions_ex[4]) & (x < regions_ex[5])

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


#correct offset excluded regions
#lineBcentre=8546.0 * u.AA
try:
    Corr_rv= rv(LINES[list(LINES.keys())[1]],float(lineBcentre/(1. * u.AA)))
except:
    Corr_rv= rv(LINES[list(LINES.keys())[1]],float(lineBcentre))


Che_model=fit_generic_continuum(spec, model=Chebyshev1D(2), 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(regions_ex[4],Corr_rv)*u.AA, corr_mask(regions_ex[5],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(8630,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8329,Corr_rv)*u.AA, corr_mask(8354,Corr_rv)*u.AA),
                                                          SpectralRegion(corr_mask(8252,Corr_rv)*u.AA, corr_mask(8256,Corr_rv)*u.AA),
                                                          ])
    
Beispiel #18
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 #19
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))
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
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 #22
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,
Beispiel #23
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 #24
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 #25
0
	wvln = deimos_spectra.loc[ deimos_spectra['name'] == spec, 'LAMBDA'].tolist()[0][0]

	""" Convert data to Spectrum1D object for specutils methods 
		First apply median filter to flux
	""" 
	filtered_flux = medfilt(flux,3)
	spectrum = Spectrum1D(filtered_flux*u.ct, spectral_axis=wvln*u.Angstrom)

	""" Lines using zero-crossings and first derivatives
		lines = find_lines_derivative(spectrum, threshold=5)

		Find lines by finding deviations larger than the noise_factor
		This method only works with continuum-subtracted spectra and the uncertainty must be defined on the spectrum
		noise_region_uncertainty does the above for us
	""" 
	noise_region = SpectralRegion(wvln[1000]*u.Angstrom, wvln[-1000]*u.Angstrom)
	spectrum = noise_region_uncertainty(spectrum, noise_region)
	lines = find_lines_threshold(spectrum, noise_factor = 1)[0][:]

	""" Search for the E/A Lines we are looking for from the lines returned by specutils """ 
	found_lines = {}
	for line in lines: 
		for n,e in EAlines.items():
			if line.value > e*(1+z)-line_window and line.value < e*(1+z)+line_window :
				found_lines.update( {n: e*(1+z)} )

	df_all.at[sid, 'Z'] = z
	df_all.at[sid, 'RA'] = RA
	df_all.at[sid, 'DEC'] = DEC

	""" If no lines found, continue """
Beispiel #26
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 #27
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 #28
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 #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 = []
Beispiel #30
0
    plt.grid(True)

    cid = fig.canvas.mpl_connect('button_press_event', clicknoise)

    plt.show()
    
selectnoise()







## looking at my plot, it seems as though between 5600 and 5800 A there is just noise
noise_region = SpectralRegion(noise[0]*u.Angstrom, noise[1]*u.Angstrom) # use SpectralRegion class to definte this noise region

## make a new spectrum where we will look for peaks that attaches some noise uncertainty
peak_spectrum = noise_region_uncertainty(spec_normalized, noise_region)


from specutils.fitting import find_lines_threshold

'''
the noise_factor is the number you would like to multiply the uncertainty by to say "a peak above this threshold
is significant". a higher noise factor means fewer peaks are selected

here I set the noise factor to 1.5* the unceratinty but we can see that it seems a few peaks are missing 
'''
lines = find_lines_threshold(peak_spectrum, noise_factor=1.5)
# with a lower noise factor you may see it finds repeated peaks once you fit each peak below