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 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 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)
def update_statistics(self): """ Retrieves the current data item in the workspace and calculates the set of statistics on its information. """ if self.hub.workspace is None or self.hub.plot_item is None: return self.clear_statistics() # If the plot item is not visible, don't bother updating stats if not self.hub.plot_item.visible: return self.clear_statistics() spec = self.hub.data_item.spectrum if self.hub.data_item is not None else None spectral_region = self._get_workspace_region() self._current_spectrum = spec self._reconnect_item_signals() # Check for issues and extract # region from input spectra: if spec is None: self.set_status("No data selected.") return self.clear_statistics() elif not isinstance(spec, Spectrum1D): self.set_status("Spectrum was not found.") return self.clear_statistics() else: spec = self._spectrum_with_plot_units(spec) if spectral_region is not None: if not check_unit_compatibility(spec, spectral_region): self.set_status("Region units are not compatible with " "selected data's spectral axis units.") return self.clear_statistics() spectral_region = clip_region(spec, spectral_region) if spectral_region is None: self.set_status("Region out of bound.") return self.clear_statistics() try: idx1, idx2 = spectral_region.bounds if idx1 == idx2: self.set_status("Region over single value.") return self.clear_statistics() spec = extract_region(spec, spectral_region) if not len(spec.flux) > 0: self.set_status("Regione range is too small.") return self.clear_statistics() except ValueError as e: self.set_status("Region could not be extracted " "from target data.") return self.clear_statistics() elif self._workspace_has_region(): self.set_status("Region has no units") return self.clear_statistics() # Compute stats and update widget: self.stats = compute_stats(spec) self._update_stat_widgets(self.stats) self.set_status(self._get_target_name())
def update_statistics(self): if self.hub.workspace is None or self.hub.plot_item is None: return self.clear_statistics() # If the plot item is not visible, don't bother updating stats if not self.hub.plot_item.visible: return self.clear_statistics() spec = self.hub.data_item.spectrum if self.hub.data_item is not None else None spectral_region = self._get_workspace_region() self._current_spectrum = spec # Check for issues and extract # region from input spectra: if spec is None: self.set_status("No data selected.") return self.clear_statistics() if spectral_region is not None: if not check_unit_compatibility(spec, spectral_region): self.set_status("Region units are not compatible with " "selected data's spectral axis units.") return self.clear_statistics() spectral_region = clip_region(spec, spectral_region) if spectral_region is None: self.set_status("Region out of bound.") return self.clear_statistics() try: idx1, idx2 = spectral_region.bounds if idx1 == idx2: self.set_status("Region over single value.") return self.clear_statistics() spec = extract_region(spec, spectral_region) except ValueError as e: self.set_status("Region could not be extracted " "from target data.") return self.clear_statistics() elif self._workspace_has_region(): self.set_status("Region has no units") return self.clear_statistics() # Compute stats and update widget: self.stats = compute_stats(spec) self._update_stat_widgets(self.stats) self.set_status(self._get_target_name())
def _add_fittable_model(self, model_type): if issubclass(model_type, models.Polynomial1D): text, ok = QInputDialog.getInt(self, 'Polynomial1D', 'Enter Polynomial1D degree:') # User decided not to create a model after all if not ok: return model = model_type(int(text)) else: model = model_type() # Grab any user-defined regions so we may initialize parameters only # for the selected data. inc_regs = self.hub.spectral_regions spec = self._get_selected_plot_data_item().data_item.spectrum if inc_regs is not None: spec = extract_region(spec, inc_regs) # Initialize the parameters model = initialize(model, spec.spectral_axis, spec.flux) self._add_model(model)
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 = []
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
###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])))
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 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
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()
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]