Exemple #1
0
    def cut_edges(self, mini, maxi):
        """Cut the spectrum in wavelength range.

        Parameters
        ----------
        mini: float
            Lower limit to cut the spectrum.

        maxi: float
            Upper limit to cut the spectrum.

        Returns
        -------
        out: NirsdustSpectrum object
            Return a new instance of class NirdustSpectrum cut in wavelength.
        """
        region = su.SpectralRegion(mini * u.AA, maxi * u.AA)
        cutted_spec1d = sm.extract_region(self.spec1d, region)
        cutted_freq_axis = cutted_spec1d.spectral_axis.to(u.Hz)
        new_len = len(cutted_spec1d.flux)
        kwargs = attr.asdict(self)
        kwargs.update(
            spec1d=cutted_spec1d,
            spectrum_length=new_len,
            frequency_axis=cutted_freq_axis,
        )

        return NirdustSpectrum(**kwargs)
Exemple #2
0
        def frecord(widget):
            wls_selected = spec_data['wl'][
                spec_data.subsets[0].to_index_list()]

            reg = specutils.SpectralRegion(
                np.min(wls_selected) * spec.wavelength.unit,
                np.max(wls_selected) * spec.wavelength.unit)
            result_text.value = 'Recorded {}: {} to {}'.format(
                line_selection.value, reg.lower, reg.upper)
            self.regions[line_selection.value] = reg

            z_text.value = specutils.analysis.centroid(
                spec, reg) / rest_lines[line_selection.value] - 1
Exemple #3
0
def measure_EW_simple(waves,
                      fluxes,
                      unc,
                      line,
                      wave_range,
                      feat_type,
                      line_width=[0., 0.],
                      plot=False,
                      file=None,
                      verbose=False,
                      name='Unknown Line',
                      diag_path=None):

    feat_type = feat_type.lower()

    #check to see if there's flux
    if np.all(np.abs(fluxes) <= 2 * unc):
        print('Warning! No flux in region for {}!'.format(name))

        res = 'No Flux'

        return res, res

    feature_waves = waves * u.AA

    feature_flux = fluxes * u.erg / (u.AA * u.s * (u.cm)**2)

    uncertainties = unc

    feature_unc = astropy.nddata.StdDevUncertainty(unc * u.erg / (u.AA * u.s *
                                                                  (u.cm)**2))

    feature_spec = specutils.Spectrum1D(spectral_axis=feature_waves,
                                        flux=feature_flux,
                                        uncertainty=feature_unc)

    continuum_fit = specutils.fitting.fit_generic_continuum(feature_spec)(
        feature_spec.spectral_axis)

    #looping to refine the continuum fit

    #initial mask around the feature
    mask = np.ones(len(feature_flux), dtype='bool')
    mask[(feature_waves.value > line_width[0])
         & (feature_waves.value < line_width[1])] = False

    subtr_spec = feature_spec - continuum_fit

    for i in range(5):

        masked_spec = specutils.Spectrum1D(spectral_axis=feature_waves[mask],
                                           flux=feature_flux[mask],
                                           uncertainty=feature_unc[mask])

        continuum_model = specutils.fitting.fit_generic_continuum(masked_spec)
        continuum_fit = continuum_model(feature_spec.spectral_axis)

        subtr_spec = feature_spec - continuum_fit

        mask = np.abs(subtr_spec.flux.value) < 3 * uncertainties

        if verbose:
            plt.plot(feature_waves, continuum_fit)
            plt.plot(feature_waves, feature_spec.flux)
            plt.title('refine {}'.format(i))
            plt.show()

    continuum_fit = continuum_model(feature_spec.spectral_axis)

    subtr_spec = feature_spec - continuum_fit

    if plot or (diag_path is not None):

        plt.figure(figsize=[12, 7])

        plt.plot(feature_spec.wavelength, feature_spec.flux)
        plt.plot(feature_spec.wavelength, continuum_fit)

        #plt.xlabel('Wavelength')
        #plt.ylabel('Flux Density')

        plt.title('Continuum fit of {}'.format(name))

        if isinstance(file, str):

            plt.savefig('kastclassify_EW_continuum_' + file)

        if diag_path is not None:

            plt.savefig(diag_path + '{}_EW_continuum_fit.png'.format(name))

        if plot:

            plt.show()

        plt.close()

    #finding line center

    near_line_waves = feature_waves[(feature_waves.value >= (line - 10))
                                    & (feature_waves.value <= (line + 10))]
    near_line_fluxes = subtr_spec.flux.value[
        (feature_waves.value >= (line - 10))
        & (feature_waves.value <= (line + 10))]

    if feat_type == 'absorption':

        line = near_line_waves.value[near_line_fluxes == np.amin(
            near_line_fluxes)]

    elif feat_type == 'emission':

        line == near_line_waves.value[near_line_fluxes == np.amax(
            near_line_fluxes)]

    else:
        print('WARNING! Feature type {} is unknown'.format(feat_type))

        res = 'Unknown Feature Type'

        return res, res

    #create continuum normalized spectrum and continuum subtracted spectrum
    norm_spec = feature_spec / continuum_fit

    #re-centering using subtracted spectrum

    #find all features in this spectrum
    line_info = specutils.fitting.find_lines_threshold(subtr_spec)

    if len(line_info) == 0:
        print('Warning! No features detected for {}!'.format(name))

        res = 'No Feature Detected'

        return res, res

    try:
        #the actual line center is the closest feature to our expected center
        nearest = np.argmin(
            np.abs(line_info[line_info['line_type'] == feat_type]
                   ['line_center'].value - line))

    except:
        print('Warning! No features detected for {}!'.format(name))

        res = 'No Feature Detected'

        return res, res

    line_center = line_info[line_info['line_type'] ==
                            feat_type][nearest]['line_center'].value

    #if the line width is not defined, calculate it
    #calculated as 1.5 * FWHM
    if line_width[0] == 0.:

        near_line_waves = feature_waves[(feature_waves.value >= (line - 15))
                                        & (feature_waves.value <=
                                           (line + 15))].value
        near_line_fluxes = subtr_spec.flux.value[
            (feature_waves.value >= (line - 15))
            & (feature_waves.value <= (line + 15))]

        if feat_type == 'absorption':

            near_line_fluxes = np.abs(near_line_fluxes)

        elif feat_type == 'emission':

            pass

        else:
            print('WARNING! Feature type {} is unknown'.format(feat_type))

            res = 'Unknown Feature Type'

            return res, res

        max_flx = np.amax(near_line_fluxes)

        half_max = max_flx / 2

        outside = near_line_fluxes < half_max

        try:
            lower_bound = max(near_line_waves[(near_line_waves < line_center)
                                              & outside])
            upper_bound = min(near_line_waves[(near_line_waves > line_center)
                                              & outside])
        except:
            print('Warning! No features detected for {}!'.format(name))

            res = 'No Feature Detected'

            return res, res

        FWHM = upper_bound - lower_bound

        line_width[0] = 1.5 * FWHM
        line_width[1] = 1.5 * FWHM

    #pick out the region containing the feature
    region = specutils.SpectralRegion((line_center - line_width[0]) * u.AA,
                                      (line_center + line_width[1]) * u.AA)

    #calculate the width
    EW = specutils.analysis.equivalent_width(norm_spec, regions=region)

    if plot or (diag_path is not None):

        fig, ax = plt.subplots(1, figsize=[12, 7])

        ax.plot(norm_spec.wavelength, norm_spec.flux, label=EW)

        ax.axvline(line_center - line_width[0])
        ax.axvline(line_center + line_width[1])

        rect = matplotlib.patches.Rectangle((line_center - EW.value / 2, 0),
                                            EW.value,
                                            1,
                                            hatch='x',
                                            fill=False)

        ax.add_patch(rect)

        ax.set_xlabel('Wavelength ({})'.format(u.AA))
        ax.set_ylabel('Normalized Flux Density')

        ax.set_title('Equivalent Width of {}'.format(name))

        fig.legend()

        if isinstance(file, str):

            fig.savefig('kastclassify_EW_width_' + file)

        if diag_path is not None:

            fig.savefig(diag_path + '{}_EW_measurement.png'.format(name))

        if plot:

            fig.show()

        plt.close(fig)

    return EW, line_center
Exemple #4
0
def test_cut_edges(NGC4945_continuum):
    spectrum = NGC4945_continuum
    region = su.SpectralRegion(20000 * u.AA, 23000 * u.AA)
    expected = su.manipulation.extract_region(spectrum.spec1d, region)
    result = spectrum.cut_edges(20000, 23000)
    np.testing.assert_array_equal(result.spec1d.flux, expected.flux)
Exemple #5
0
 def regions(self):
     wmin, wmax = self.wavelength[[0, -1]]
     return specutils.SpectralRegion(wmin, wmax)