def on_action_triggered(self): # Get the currently selected data item spec = self.hub.data_item.spectrum # Retreive any rois to be used for exclusion in the continuum fit. # TODO: need an easy way to invert this to satisfy the formalism of # specutils where *excluded* regions are passed in. inc_regs = self.hub.spectral_regions exc_regs = inc_regs.invert_from_spectrum(spec) # Perform the continuum fitting, storing both model and array output cont_mod = fit_generic_continuum(spec, exclude_regions=exc_regs) y_cont = cont_mod(spec.spectral_axis) # Construct the new spectrum object containing the array new_spec = Spectrum1D(flux=y_cont, spectral_axis=spec.spectral_axis) # Add the continuum model to the model data item's fitting model model_fitting_model = ModelFittingModel() model_fitting_model.add_model(cont_mod.unitless_model) # Create a new model data item to be added to the data list model_data_item = ModelDataItem(model=model_fitting_model, name="Continuum (auto-generated)", identifier=uuid.uuid4(), data=new_spec) # Add the model data item to the internal qt model self.hub.append_data_item(model_data_item)
def on_action_triggered(self): """ The action triggered via interaction with the UI. Generates the continuum for the selected regions on the spectrum. """ # Get the currently selected data item spec = self.hub.data_item.spectrum # Retrieve any rois to be used for exclusion in the continuum fit. inc_regs = self.hub.spectral_regions exc_regs = inc_regs.invert_from_spectrum(spec) \ if inc_regs is not None else None # Perform the continuum fitting, storing both model and array output cont_mod = fit_generic_continuum(spec, exclude_regions=exc_regs) y_cont = cont_mod(spec.spectral_axis) # Construct the new spectrum object containing the array new_spec = Spectrum1D(flux=y_cont, spectral_axis=spec.spectral_axis) # Add the continuum model to the model data item's fitting model model_fitting_model = ModelFittingModel() model_fitting_model.add_model(cont_mod.unitless_model) # Create a new model data item to be added to the data list model_data_item = ModelDataItem(model=model_fitting_model, name="Continuum (auto-generated)", identifier=uuid.uuid4(), data=new_spec) # Add the model data item to the internal qt model self.hub.append_data_item(model_data_item)
def norm(wl,fl): fl = fl * u.Unit('J cm-2 s-1 AA-1') wl = wl * u.AA spec = Spectrum1D(spectral_axis=wl, flux=fl) fln = spec / fit_generic_continuum(spec)(spec.spectral_axis) fln = [float(i) for i in fln.flux ] fln = np.array(fln) return fln
def fit_continuum(spectrum): """Fits continuum to a spectrum Parameters ---------- spectrum : specutils.Spectrum1D Spectrum to which the continuum is to be fitted Returns ------- numpy.NDArray Array of values for the fitted continuum flux """ fitted_continuum = fit_generic_continuum(spectrum) return fitted_continuum(spectrum.spectral_axis)
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)
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')
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, polyOrder=1, widthFactor=10, verbose=1) print(line.get_line_centre(), line.get_line_peak(), line.get_line_fwhm())
''' since stars have a black body continuum spectrum, we would like to subtract that out to look specifically at the absorption and emission lines we will use specutils fit_generic_continuum to fit a continuum ''' ## use specutils.fit_generic_continuum to build a conintuum function to the data continuum_fit = fit_generic_continuum(spec) print(continuum_fit) ## plug the wavelengths into your continuum function intensity_continuum_fitted = continuum_fit(calib_wavelengths*u.Angstrom) ## Plot the original spectrum and the fitted and the continuum plt.figure() plt.plot(spec.spectral_axis, spec.flux, label='spectrum') plt.plot(spec.spectral_axis, intensity_continuum_fitted, label='continuum') plt.xlabel('wavelength (Å)') plt.ylabel('flux') plt.title('Continuum Fitting') plt.grid(True) plt.legend()
#trim spectrum mask = (wl > lamb1) & (wl < lamb2) wl = wl[mask] fl = fl[mask] spectrum = Spectrum1D(flux=fl * u.Jy, spectral_axis=wl * u.AA) # start end start end regions = [8489.0, 8563.0, 8642.0, 8697.0] if interactive_mode == False: g1_fit = fit_generic_continuum(spectrum, exclude_regions=[ SpectralRegion(regions[0] * u.AA, regions[1] * u.AA), SpectralRegion(regions[2] * u.AA, regions[3] * u.AA) ]) y_continuum_fitted = g1_fit(wl * u.AA) spec_normalized = spectrum / y_continuum_fitted print(FILENAME + 'was normalized automaticaly... \n') #add a spline with a selected dots #-------------------------------- if interactive_mode == True: f0 = plt.figure(figsize=(12, 7)) ax0 = f0.add_subplot(111)
def subtract_continuum( self, poly_degree: int = 3, plot_filename: Optional[str] = "continuum.pdf", spec_filename: Optional[str] = None, ) -> None: """ Method for fitting the continuum with a polynomial function of the following form: :math:`P = \\sum_{i=0}^{i=n}C_{i} * x^{i}`. The spectrum is first smoothed with a median filter and then fitted with a linear least squares algorithm. Parameters ---------- poly_degree : int Degree of the polynomial series. plot_filename : str, None Filename for the plots with the continuum fit and the continuum-subtracted spectrum. The plot is shown in an interface window if the argument is set to ``None``. spec_filename : str, None Output text file for writing the continuum-subtracted spectrum. The file will not be created if the argument is set to ``None``. Returns ------- NoneType None """ # Fit continuum print("Fitting continuum...", end="", flush=True) spec_extract = Spectrum1D( flux=self.spectrum[:, 1] * u.W, spectral_axis=self.spectrum[:, 0] * u.um, uncertainty=StdDevUncertainty(self.spectrum[:, 2] * u.W), ) g1_fit = fit_generic_continuum( spec_extract, median_window=3, model=Polynomial1D(poly_degree), fitter=LinearLSQFitter(), ) continuum_fit = g1_fit(spec_extract.spectral_axis) print(" [DONE]") # Subtract continuum spec_cont_sub = spec_extract - continuum_fit self.continuum_flux = continuum_fit / u.W # Create plot if plot_filename is None: print("Plotting continuum fit...", end="", flush=True) else: print(f"Plotting continuum fit: {plot_filename}...", end="", flush=True) mpl.rcParams["font.serif"] = ["Bitstream Vera Serif"] mpl.rcParams["font.family"] = "serif" plt.rc("axes", edgecolor="black", linewidth=2) plt.rcParams["axes.axisbelow"] = False plt.figure(1, figsize=(6, 6)) gs = mpl.gridspec.GridSpec(2, 1) gs.update(wspace=0, hspace=0.1, left=0, right=1, bottom=0, top=1) ax1 = plt.subplot(gs[0, 0]) ax2 = plt.subplot(gs[1, 0]) ax3 = ax1.twiny() ax4 = ax2.twiny() ax1.tick_params( axis="both", which="major", colors="black", labelcolor="black", direction="in", width=1, length=5, labelsize=12, top=False, bottom=True, left=True, right=True, labelbottom=False, ) ax1.tick_params( axis="both", which="minor", colors="black", labelcolor="black", direction="in", width=1, length=3, labelsize=12, top=False, bottom=True, left=True, right=True, labelbottom=False, ) ax2.tick_params( axis="both", which="major", colors="black", labelcolor="black", direction="in", width=1, length=5, labelsize=12, top=False, bottom=True, left=True, right=True, ) ax2.tick_params( axis="both", which="minor", colors="black", labelcolor="black", direction="in", width=1, length=3, labelsize=12, top=False, bottom=True, left=True, right=True, ) ax3.tick_params( axis="both", which="major", colors="black", labelcolor="black", direction="in", width=1, length=5, labelsize=12, top=True, bottom=False, left=True, right=True, ) ax3.tick_params( axis="both", which="minor", colors="black", labelcolor="black", direction="in", width=1, length=3, labelsize=12, top=True, bottom=False, left=True, right=True, ) ax4.tick_params( axis="both", which="major", colors="black", labelcolor="black", direction="in", width=1, length=5, labelsize=12, top=True, bottom=False, left=True, right=True, labeltop=False, ) ax4.tick_params( axis="both", which="minor", colors="black", labelcolor="black", direction="in", width=1, length=3, labelsize=12, top=True, bottom=False, left=True, right=True, labeltop=False, ) ax1.set_ylabel("Flux (W m$^{-2}$ µm$^{-1}$)", fontsize=16) ax2.set_xlabel("Wavelength (µm)", fontsize=16) ax2.set_ylabel("Flux (W m$^{-2}$ µm$^{-1}$)", fontsize=16) ax3.set_xlabel("Velocity (km s$^{-1}$)", fontsize=16) ax1.get_yaxis().set_label_coords(-0.1, 0.5) ax2.get_xaxis().set_label_coords(0.5, -0.1) ax2.get_yaxis().set_label_coords(-0.1, 0.5) ax3.get_xaxis().set_label_coords(0.5, 1.12) ax1.plot( spec_extract.spectral_axis, spec_extract.flux, color="black", label=self.spec_name, ) ax1.plot( spec_extract.spectral_axis, continuum_fit, color="tab:blue", label="Continuum fit", ) ax2.plot( spec_cont_sub.spectral_axis, spec_cont_sub.flux, color="black", label="Continuum subtracted", ) ax3.plot(self.spec_vrad, spec_extract.flux, ls="-", lw=0.0) ax4.plot(self.spec_vrad, spec_cont_sub.flux, ls="-", lw=0.0) ax1.legend(loc="upper right", frameon=False, fontsize=12.0) ax2.legend(loc="upper right", frameon=False, fontsize=12.0) print(" [DONE]") if plot_filename is None: plt.show() else: plt.savefig(plot_filename, bbox_inches="tight") plt.clf() plt.close() # Overwrite original spectrum with continuum-subtracted spectrum self.spectrum[:, 1] = spec_cont_sub.flux self.continuum_check = True if spec_filename is not None: print( f"Writing continuum-subtracted spectrum: {spec_filename}...", end="", flush=True, ) header = "Wavelength (um) - Flux (W m-2 um-1) - Error (W m-2 um-1)" np.savetxt(spec_filename, self.spectrum, header=header) print(" [DONE]")
#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), ]) #Chebyshev parameters C0=float(Che_model.c0.value) C1=float(Che_model.c1.value) C2=float(Che_model.c2.value) #C3=float(Che_model.c3.value)
def Load_Files(file_1, file_2, N_sample, objts, classification=False): print('INFO:') #hdul = fitsio.FITS(file_1) # Open file 1 -- 'truth_DR12Q.fits' #info=hdul.info() # File info hdul = fits.open(file_1, mode='denywrite') #data=hdul[1].read() # Database of spectra with human-expert classifications data = hdul[1].data #print('The file {} have {} objects. \n'.format(file_1,data.shape[0])) print('INFO:') # Reading data from data_dr12.fits. This file had the spectra from data dr12. #hdul_2 = fitsio.FITS(file_2) # Open file 2 -- 'data_dr12.fits' #info2=hdul_2.info() # File info #data2=hdul_2[1].read() # Database of spectra #spectra=hdul_2[0].read() # Spectrum of each object hdul_2 = fits.open(file_2, mode='denywrite') data2 = hdul_2[1].data # Database of spectra spectra = hdul_2[0].data # Spectrum of each object #print('The file {} have {} spectra. \n'.format(file_2,spectra.shape[0])) # Subset of PLATE parameters of both data data_PLATE_1 = data['PLATE'] data_PLATE_2 = data2['PLATE'] # Subset of MJD parameters of both data data_MJD_1 = data['MJD'] data_MJD_2 = data2['MJD'] # Subset of FIBERID parameters of both data data_FIBERID_1 = data['FIBERID'] data_FIBERID_2 = data2['FIBERID'] data_ID_1 = data['THING_ID'] data_ID_2 = data2['TARGETID'] objts = np.asarray(objts) # The column 'CLASS_PERSON' have a class identifier for each spectrum: STARS=1, GALAXY=4, QSO=3 and QSO_BAL=30. C_P = data['CLASS_PERSON'] #Class Person column STAR = C_P[C_P == 1] # objects classified as stars GALAXY = C_P[C_P == 4] # objects classified as galaxies QSO = C_P[C_P == 3] # objects classified as QSO (Quasars) QSO_BAL = C_P[ C_P == 30] # objects classified as QSO BAL (Quasars with Broad Absortions Lines) N_C = C_P[C_P != 30] N_C = N_C[N_C != 3] N_C = N_C[N_C != 1] N_C = N_C[N_C != 4] # objects wrong classified print('INFO: There is available') print('-->Star:', STAR.shape[0]) print('-->Galaxy:', GALAXY.shape[0]) print('-->QSO:', QSO.shape[0]) print('-->QSO BAL:', QSO_BAL.shape[0]) print('-->NN: {}\n'.format(N_C.shape[0])) # I create two DataFrame for Superset_DR12Q and data_dr12 with only three parameters data1 = { 'PLATE': data_PLATE_1, 'MJD': data_MJD_1, 'FIBERID': data_FIBERID_1, 'ID': data_ID_1 } data1 = pd.DataFrame(data=data1) data2 = { 'PLATE': data_PLATE_2, 'MJD': data_MJD_2, 'FIBERID': data_FIBERID_2, 'ID': data_ID_2 } data2 = pd.DataFrame(data=data2) # I convert all objects in both set to string chain in orden to combine them as one new ID. data1['PLATE'] = data1['PLATE'].astype(str) data1['MJD'] = data1['MJD'].astype(str) data1['FIBERID'] = data1['FIBERID'].astype(str) data1['PM'] = data1['MJD'].str.cat(data1['FIBERID'], sep="-") data1['NEWID'] = data1['PLATE'].str.cat(data1['PM'], sep="-") data_1 = data1.drop(columns=['PLATE', 'MJD', 'FIBERID', 'ID', 'PM']).values data2['PLATE'] = data2['PLATE'].astype(str) data2['MJD'] = data2['MJD'].astype(str) data2['FIBERID'] = data2['FIBERID'].astype(str) data2['PM'] = data2['MJD'].str.cat(data2['FIBERID'], sep="-") data2['NEWID'] = data2['PLATE'].str.cat(data2['PM'], sep="-") data_2 = data2.drop(columns=['PLATE', 'MJD', 'FIBERID', 'ID', 'PM'] ).values # New set of database 2 with new ID's # With the routine of numpy intersect1d, I find the intersections elements in both sets. This elements data_CO = np.array(np.intersect1d(data_1, data_2, return_indices=True)) data_CO_objects = data_CO[ 0] # The unique new ID of each element in both sets data_CO_ind1 = data_CO[ 1] # Indices of intersected elements from the original data 1 (Superset_DR12Q.fits) data_CO_ind2 = data_CO[ 2] # Indices of intersected elements form the original data 2 (data_dr12.fits) print('INFO:') print('I find {} objects with spectra from DR12 \n'.format( len(data_CO_objects))) indi = {'ind1': data_CO_ind1, 'ind2': data_CO_ind2} ind = pd.DataFrame(data=indi, index=data_CO_ind1) cp = np.array(data['CLASS_PERSON'], dtype=float) z = np.array(data['Z_VI'], dtype=float) zc = np.array(data['Z_CONF_PERSON'], dtype=float) bal = np.array(data['BAL_FLAG_VI'], dtype=float) bi = np.array(data['BI_CIV'], dtype=float) d = { 'CLASS_PERSON': cp, 'Z_VI': z, 'Z_CONF_PERSON': zc, 'BAL_FLAG_VI': bal, 'BI_CIV': bi } data_0 = pd.DataFrame(data=d) obj = data_0.loc[data_CO_ind1] if (classification != True): if (objts[0] == 'QSO'): qsos = obj.loc[obj['CLASS_PERSON'] == 3] qsos = qsos.loc[qsos['Z_CONF_PERSON'] == 3] sample_objects = qsos.sample(n=int(N_sample), weights='CLASS_PERSON', random_state=5) indi = np.array(sample_objects.index) indi1 = ind.loc[indi].values elif (objts[0] == 'QSO_BAL'): qsos_bal = obj.loc[obj['CLASS_PERSON'] == 30] qsos_bal = qsos_bal.loc[qsos_bal['Z_CONF_PERSON'] == 3] sample_objects = qsos_bal.sample(n=int(N_sample), weights='CLASS_PERSON', random_state=5) indi = np.array(sample_objects.index) indi1 = ind.loc[indi].values elif (len(objts) == 2): qsos = obj.loc[obj['CLASS_PERSON'] == 3] qsos = qsos.loc[qsos['Z_CONF_PERSON'] == 3] qsos_bal = obj.loc[obj['CLASS_PERSON'] == 30] qsos_bal = qsos_bal.loc[qsos_bal['Z_CONF_PERSON'] == 3] sample_qso = qsos.sample(n=int(N_sample / 2), weights='CLASS_PERSON', random_state=5) sample_qso_bal = qsos_bal.sample(n=int(N_sample / 2), weights='CLASS_PERSON', random_state=5) sample_objects = pd.concat([sample_qso, sample_qso_bal]) ind_qso = np.array(sample_qso.index) ind_qso_bal = np.array(sample_qso_bal.index) indi = np.concatenate((ind_qso, ind_qso_bal), axis=None) indi1 = ind.loc[indi].values spectra_ = np.zeros((N_sample, 886)) j = 0 kernel_size = 5 flux_threshold = 1.1 parameters = np.zeros( (N_sample, 7) ) #Number of lines // FHWM of max emission line // EW of max emission line // Spectrum Mean // Spectrum STDV // Spectrum Flux Integral // Spectrum SNR for i in indi: k = indi1[j, 1] x = np.linspace(3600, 10500, 443) zero_spectrum = spectra[k, :443] spectrum = Spectrum1D(flux=zero_spectrum * u.Jy, spectral_axis=x * u.AA) #Continuum fit and gaussian smooth g1_fit = fit_generic_continuum(spectrum) y_continuum_fitted = g1_fit(x * u.AA) spec_nw_2 = spectrum / y_continuum_fitted spectrum_smooth = gaussian_smooth(spec_nw_2, kernel_size) #Number of lines lines_1 = find_lines_derivative(spectrum_smooth, flux_threshold=flux_threshold) l = lines_1[lines_1['line_type'] == 'emission'] number_lines = l['line_center_index'].shape[0] parameters[j, 0] = number_lines #FWHM parameters[j, 1] = fwhm(spectrum_smooth).value #EW parameters[j, 2] = equivalent_width(spectrum_smooth).value #Spectrum Mean parameters[j, 3] = np.mean(spectrum_smooth.flux) #Spectrum STDV parameters[j, 4] = np.std(spectrum_smooth.flux) #Spectrum Flux Integral parameters[j, 5] = line_flux(spectrum_smooth).value #Spectrum SNR parameters[j, 6] = snr_derived(spectrum_smooth).value j += 1 d = { 'Lines_Number': parameters[:, 0], 'FHWM': parameters[:, 1], 'EW': parameters[:, 2], 'Mean': parameters[:, 3], 'STDV': parameters[:, 4], 'STDV': parameters[:, 4], 'Spectrum_Flux': parameters[:, 5], 'SNR': parameters[:, 6] } parameters = pd.DataFrame(data=d) #X=spectra_.values #mean_flx= np.ma.average(X[:,:443],axis=1) #ll=(X[:,:443]-mean_flx.reshape(-1,1))**2 #aveflux=np.ma.average(ll, axis=1) #sflux = np.sqrt(aveflux) #X = (X[:,:443]-mean_flx.reshape(-1,1))/sflux.reshape(-1,1) y = sample_objects['Z_VI'] y = np.array(y, dtype=float) #y_max=np.max(y) #y=y/y_max return parameters, y stars = obj.loc[obj['CLASS_PERSON'] == 1] galaxies = obj.loc[obj['CLASS_PERSON'] == 4] qsos = obj.loc[obj['CLASS_PERSON'] == 3] qsos_bal = obj.loc[obj['CLASS_PERSON'] == 30] sample_star = stars.sample(n=int(N_sample / 4), weights='CLASS_PERSON', random_state=5) sample_galaxy = galaxies.sample(n=int(N_sample / 4), weights='CLASS_PERSON', random_state=5) sample_qso = qsos.sample(n=int(N_sample / 4), weights='CLASS_PERSON', random_state=5) sample_qso_bal = qsos_bal.sample(n=int(N_sample / 4), weights='CLASS_PERSON', random_state=5) sample_objects = pd.concat( [sample_star, sample_galaxy, sample_qso, sample_qso_bal]) ind_star = np.array(sample_star.index) ind_galaxy = np.array(sample_galaxy.index) ind_qso = np.array(sample_qso.index) ind_qso_bal = np.array(sample_qso_bal.index) indi = np.concatenate((ind_star, ind_galaxy, ind_qso, ind_qso_bal), axis=None) indi1 = ind.loc[indi].values spectra_ = np.zeros((N_sample, 886)) j = 0 for i in indi: k = indi1[j, 1] spectra_[j, :] = spectra[k, :] j = j + 1 spectra_ = pd.DataFrame(spectra_) X = spectra_.values #Renormalize spectra mean_flx = np.ma.average(X[:, :443], axis=1) ll = (X[:, :443] - mean_flx.reshape(-1, 1))**2 aveflux = np.ma.average(ll, axis=1) sflux = np.sqrt(aveflux) X = (X[:, :443] - mean_flx.reshape(-1, 1)) / sflux.reshape(-1, 1) y = sample_objects['CLASS_PERSON'] y = y.replace([1, 4, 3, 30], [0, 1, 2, 3]).values y = np.array(y, dtype=float) return X, y
wavln = wvln[index:] spectrum = Spectrum1D(spectral_axis = wavln * u.angstrom, flux = spec * u.erg/u.s/u.cm/u.cm/u.angstrom) #In order to have the best chance for finding the emission lnes we need to get rid #of the continuum shape and for this we need the fitting models we imported above to #fit the shape ############ #Example of fitting a continuum with the data that I was able to get. ############ #This fits it with a weird model but we can change it to linear as thats what #the program tells me to do continuum_fit = fit_generic_continuum(spectrum, model=models.Linear1D()) #the above return a function that i can pass in x values to fit the continuum #ideally this would be the whole spectrum wavelength range y=continuum_fit(spectrum.spectral_axis) centered_spec = Spectrum1D(spectral_axis=spectrum.spectral_axis, flux= spectrum.flux - y) #getting the emission and absorption lines using threshold #NOTE: We need to have noise in order for me to use this and can be done using # noise_region_uncertainty lines = find_lines_threshold(spectrum, noise_factor=3) #Another way that we can find emission and absorption lines is by using line derivatives
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)]) C0=float(Che_model.c0.value) C1=float(Che_model.c1.value) C2=float(Che_model.c2.value) C3=float(Che_model.c3.value)
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()
plt.xlabel(r'$\lambda$ ($\AA$)',fontsize=11) plt.ylabel('ADU',fontsize=11) plt.title('Spectrum of HD 32991',fontsize=11) plt.show(block=False) spectra=np.column_stack((w,sf)) np.savetxt('/home/ganesh/Desktop/spectpf.txt',spectra, newline='\n',delimiter=',') #fitting spectrum data2=pd.read_csv('/home/ganesh/Desktop/spectpf.txt',header=None) y=u.Quantity(data2[1],u.dimensionless_unscaled) x=u.Quantity(data2[0],u.angstrom) spectrum = Spectrum1D(spectral_axis=x,flux=y) g1_fit = fit_generic_continuum(spectrum) y_continuum_fitted = g1_fit(x) #continuum fitted spectrum plt.figure() plt.plot(x, y,'k') plt.plot(x, y_continuum_fitted, 'orange') plt.xlabel(r'$\lambda$ ($\AA$)',fontsize=11) plt.show(block=False) #Plot continuum normalised intensity spec_normalized = spectrum / y_continuum_fitted t=QTable([spec_normalized.spectral_axis,spec_normalized.flux]) t.write('/home/ganesh/Desktop/spectf.txt',format='ascii', delimiter=',')
def norm_spectrum(spec, median_window=3, order=3): ''' Normalize a spectrum Parameters: ----------- spec: specutils.Spectrum1D Spectrum to normalize median_window: int() Window in Pixel used in median smoothing order: int() Order of the polynomial used to find the continuum Returns: -------- norm_spec: specutils.Spectrum1D Normalized spectrum ''' # Regions that should not be used for continuum estimation, # such as broad atmospheric absorption bands exclude_regions = [ SpectralRegion(4295. * u.AA, 4315. * u.AA), #SpectralRegion(6860.* u.AA, 6880.* u.AA), SpectralRegion(6860. * u.AA, 6910. * u.AA), #SpectralRegion(7590.* u.AA, 7650.* u.AA), SpectralRegion(7590. * u.AA, 7680. * u.AA), SpectralRegion(9260. * u.AA, 9420. * u.AA), #SpectralRegion(11100.* u.AA, 11450.* u.AA), #SpectralRegion(13300.* u.AA, 14500.* u.AA), ] # First estimate of the continuum # -> will be two for late type stars because of the many absorption lines # -> to limit execution time use simple LinearLSQFitter() # -> reduces normalization accuracy _cont = fit_generic_continuum( spec, model=models.Chebyshev1D(order), fitter=fitting.LinearLSQFitter(), median_window=median_window, exclude_regions=exclude_regions, )(spec.spectral_axis) # Normalize spectrum norm_spec = spec / _cont # Sigma clip the normalized spectrum to rm spectral lines clip_flux = sigma_clip( norm_spec.flux, sigma_lower=1.25, sigma_upper=3., axis=0, grow=1., ) # Calculate mask mask = np.invert(clip_flux.recordmask) # Make new spectrum spec_mask = Spectrum1D( spectral_axis=spec.spectral_axis[mask], flux=spec.flux[mask], ) # Determine new continuum _cont = fit_generic_continuum( spec_mask, model=models.Chebyshev1D(order), fitter=fitting.LinearLSQFitter(), median_window=median_window, exclude_regions=exclude_regions, )(spec.spectral_axis) # Normalize spectrum again norm_spec = spec / _cont return norm_spec, mad_std(norm_spec.flux)
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)
from specutils.fitting import fit_generic_continuum cont_norm_spec = spec / fit_generic_continuum(spec)(spec.spectral_axis) f, ax = plt.subplots() # doctest: +IGNORE_OUTPUT ax.step(cont_norm_spec.wavelength, cont_norm_spec.flux) # doctest: +IGNORE_OUTPUT ax.set_xlim(654 * u.nm, 660 * u.nm) # doctest: +IGNORE_OUTPUT +REMOTE_DATA
specdata = f[1].data # doctest: +REMOTE_DATA z = cz.loc[gal][0] / 3e5 #z = f[2].data.Z[0] print(z) f.close() lamb_full = 10**specdata['loglam'] * u.AA # doctest: +REMOTE_DATA lamb = lamb_full[lamb_full < 6900 * u.AA] flux = specdata['flux'] * 10**-17 * u.Unit( 'erg cm-2 s-1 AA-1') # doctest: +REMOTE_DATA flux = flux[lamb_full < 6900 * u.AA] spec = Spectrum1D(spectral_axis=lamb, flux=flux) # doctest: +REMOTE_DATA cont_norm_spec = spec / fit_generic_continuum(spec)( spec.spectral_axis) # doctest: +REMOTE_DATA wave = np.array(cont_norm_spec.wavelength) flux = np.array(cont_norm_spec.flux) new_wave = wave / (1 + z) #/3e5)) new_flux = flux * (1 + z) #/3e5))#rebin_spec(new_wave,flux,wave) new_spec = Spectrum1D( spectral_axis=new_wave * u.AA, flux=new_flux * u.Unit('erg cm-2 s-1 AA-1')) # doctest: +REMOTE_DATA heii_wave = new_wave[(new_wave > 4665) & (new_wave < 4705)] heii_flux = new_flux[(new_wave > 4665) & (new_wave < 4705)] heii_spec = Spectrum1D( spectral_axis=heii_wave * u.AA, flux=heii_flux *
#input command for redshift redshift = float(input('Input Redshift of SNe:')) z = 1 + redshift #turn each file name into array #apply obs to rest wavelength and flux conversion #create list of spectrum files, and continuum files cont_list = [] data = [] for epoch in file_list: file = np.genfromtxt(fname= epoch) lamb = (file[:, 0] / z) * u.AA flux = file[:, 1] * 10 ** -15 * u.Unit('erg cm-2 s-1 AA-1') spec = Spectrum1D(spectral_axis=lamb, flux=flux) data.append(spec) cont_list.append((spec /spec) * fit_generic_continuum(spec)(spec.spectral_axis)) #plot to find the lines to calculate EW spcplt = data[0] cntplt = cont_list[0] f, ax = plt.subplots() ax.step(spcplt.wavelength, spcplt.flux) ax.step(cntplt.wavelength, cntplt.flux) ax.set_xlim(6000*u.AA, 7500*u.AA) ax.grid(True) wave = [6563, 6678, 7065, 7155] for line in wave: plt.axvline(x = line) plt.show()
redshift = float(input('Input Redshift of SNe:')) z = 1 + redshift #turn each file name into array #apply obs to rest wavelength and flux conversion #create list of spectrum files, and continuum files cont_list = [] data = [] for epoch in file_list: file = np.genfromtxt(fname=epoch) lamb = (file[:, 0] / z) * u.AA flux = file[:, 1] * 10**-15 * u.Unit('erg cm-2 s-1 AA-1') spec = Spectrum1D(spectral_axis=lamb, flux=flux) data.append(spec) cont_list.append( (spec / spec) * fit_generic_continuum(spec)(spec.spectral_axis)) #plot to find the lines to calculate EW spcplt = data[0] cntplt = cont_list[0] f, ax = plt.subplots() ax.step(spcplt.wavelength, spcplt.flux) ax.step(cntplt.wavelength, cntplt.flux) ax.set_xlim(5650 * u.AA, 6500 * u.AA) ax.grid(True) wave = [5755, 5876, 6248, 6300] for line in wave: plt.axvline(x=line) plt.show() #Identify the Region for flux extraction
def fit_line(name, wave, flux, err, z): rest_wave = wave uncertainty = StdDevUncertainty(err * u.Jy) spec1 = Spectrum1D(spectral_axis=rest_wave * u.AA, flux=flux * u.Jy, uncertainty=uncertainty) spec = box_smooth(spec1, width=3) nev_region = SpectralRegion(3395 * u.AA, 3408 * u.AA) + SpectralRegion( 3440 * u.AA, 3456 * u.AA) nev_lineregion = SpectralRegion(3415 * u.AA, 3435 * u.AA) nev_spec = extract_region(spec, SpectralRegion(3390 * u.AA, 3460 * u.AA)) line_spec = extract_region(nev_spec, nev_lineregion) # nev_spec = extract_region(spec,nev_region) # SNR1 = snr(line_spec) ###median snr line_cont = fit_generic_continuum(nev_spec, exclude_regions=nev_lineregion) cont_fit = line_cont(nev_spec.spectral_axis) # peak1 = centroid(nev_spec) norm_nev_spec = Spectrum1D(spectral_axis=nev_spec.spectral_axis, flux=nev_spec.flux / cont_fit) sub_nev_spec = Spectrum1D(spectral_axis=nev_spec.spectral_axis, flux=nev_spec.flux - cont_fit) line_fit = kmpfit.Fitter(residuals = _residuals,data = (sub_nev_spec.spectral_axis/u.AA,\ sub_nev_spec.flux/u.Jy,\ nev_spec.uncertainty.array)) line_fit_ini = [0, 3426, 3] line_fit.parinfo = [{ 'limits': (0., 10.**10) }, { 'limits': (3416, 3436) }, { 'limits': (0, 6) }] line_fit.fit(params0=line_fit_ini) snrregion = SpectralRegion( (line_fit.params[1] - 2 * line_fit.params[2]) * u.AA, (line_fit.params[1] + 2 * line_fit.params[2]) * u.AA) # print(snrregion) calc_spectrum = extract_region(nev_spec, snrregion) flux = calc_spectrum.flux uncertainty = calc_spectrum.uncertainty.array * nev_spec.uncertainty.unit SNR = np.median(flux / uncertainty, axis=-1) peak = line_fit.params[1] wave = nev_spec.spectral_axis / u.AA # print(snr(nev_spec,snrregion).value) plt.figure() plt.plot(nev_spec.spectral_axis, nev_spec.flux) plt.plot(nev_spec.spectral_axis, cont_fit, 'orange') plt.plot(nev_spec.spectral_axis, nev_spec.uncertainty.array, 'grey') plt.plot(sub_nev_spec.spectral_axis, sub_nev_spec.flux, 'green') plt.axvline(3426.) plt.plot(nev_spec.spectral_axis / u.AA, onegauss(nev_spec.spectral_axis / u.AA, line_fit.params), 'r') plt.savefig('/Users/k/Documents/MMT_spec/MMT_LockmanHole/NeV/24b_NeV/' + name + '.eps', format='eps', dpi=300) # plt.close() return SNR, line_fit.params[1]