def mkklam(lam, dlsf, dfiblam, klamfile): # Returns atmospheric extinction coefficient sampled at wavelengths in "lam" # The klam curve is convolved to the spectrograph LSF and the fiber width before sampling it #data=ascii.read('/Users/gblancm/work/LCO/lcoetc/database/sky/klam.dat') data = ascii.read(klamfile) # trim to lrange only lam0 = data['col1'][(data['col1'] > np.amin(lam)) * (data['col1'] < np.amax(lam))] klam0 = data['col2'][(data['col1'] > np.amin(lam)) * (data['col1'] < np.amax(lam))] # interpolate to regular grid ddisp0 = np.median(lam0[1:len(lam0) - 1] - lam0[0:len(lam0) - 2]) lam1 = np.arange(np.amin(lam0), np.amax(lam0), ddisp0) f = interp1d(lam0, klam0, fill_value='extrapolate') klam1 = f(lam1) # convolve with LSF (Gaussian of FWHM=dlsf) gauss = conv.Gaussian1DKernel(stddev=dlsf / 2.355 / ddisp0, x_size=round_up_to_odd(10 * dlsf / 2.355 / ddisp0)) klam2 = conv.convolve(klam1, gauss.array, boundary='extend') # convolve with fiber profile (Gaussian of FWHM=dfiberlam) gauss = conv.Gaussian1DKernel(stddev=dfiblam / 2.355 / ddisp0, x_size=round_up_to_odd(10 * dfiblam / 2.355 / ddisp0)) klam3 = conv.convolve(klam2, gauss.array, boundary='extend') # interpolate to lam f = interp1d(lam1, klam3, fill_value='extrapolate') return f(lam)
def mkslam(lam, dlsf, dfiblam, sfile): # Returns sky surface brightness spectrum for a given moon phase, LSF FWHM, and slit width. # The result is convolved with LSF+slit and sampled at wavelengths in lam data = ascii.read(sfile) # trim to lrange only lam0 = data['col1'][(data['col1'] > np.amin(lam)) * (data['col1'] < np.amax(lam))] slam0 = data['col2'][(data['col1'] > np.amin(lam)) * (data['col1'] < np.amax(lam))] # interpolate to regular grid ddisp0 = np.median(lam0[1:len(lam0) - 1] - lam0[0:len(lam0) - 2]) lam1 = np.arange(np.amin(lam0), np.amax(lam0), ddisp0) f = interp1d(lam0, slam0, fill_value='extrapolate') slam1 = f(lam1) # convolve with LSF (Gaussian of FWHM=dlsf) gauss = conv.Gaussian1DKernel(stddev=dlsf / 2.355 / ddisp0, x_size=round_up_to_odd(10 * dlsf / 2.355 / ddisp0)) slam2 = conv.convolve(slam1, gauss.array, boundary='extend') # convolve with fiber profile (Gaussian with FWHM=dfiblam) gauss = conv.Gaussian1DKernel(stddev=dfiblam / 2.355 / ddisp0, x_size=round_up_to_odd(10 * dfiblam / 2.355 / ddisp0)) slam3 = conv.convolve(slam2, gauss.array, boundary='extend') logf.write(str(np.mean(slam1)) + '\n') logf.write(str(np.mean(slam2)) + '\n') logf.write(str(np.mean(slam3)) + '\n') # interpolate to lam f = interp1d(lam1, slam3, fill_value='extrapolate') return f(lam)
def test_spectral_smooth(): cube, data = cube_and_raw('522_delta.fits') result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0)) np.testing.assert_almost_equal( result[:, 0, 0].value, convolution.Gaussian1DKernel(1.0, x_size=5).array, 4)
def mklinelam(lam, dlsf, dfiblam, linelam, lineflux, linefwhm): sigma=linefwhm/2.355 linelam1=lineflux/(np.sqrt(2)*sigma)*np.exp(-1*(lam-linelam)**2/(2*sigma**2)) # convolve with LSF (Gaussian of FWHM=dlsf) ddisp0=np.median(lam[1:len(lam)-1]-lam[0:len(lam)-2]) gauss=conv.Gaussian1DKernel(stddev=dlsf/2.355/ddisp0, x_size=round_up_to_odd(10*dlsf/2.355/ddisp0)) linelam2=conv.convolve(linelam1, gauss.array, boundary='extend') # convolve with fiber profile (Gaussian with FWHM=dfiblam) gauss=conv.Gaussian1DKernel(stddev=dfiblam/2.355/ddisp0, x_size=round_up_to_odd(10*dfiblam/2.355/ddisp0)) linelam3=conv.convolve(linelam2, gauss.array, boundary='extend') return linelam3
def convolve_spectrum(target_spec, header, kernel_type='gaussian', pix_width=pix_width, kernel_width=slit_width, double_smooth=False): #pix_width =3 #pix_width =20 fluxes = np.copy(target_spec[1]) wavelengths = np.copy(target_spec[0]) if kernel_type == 'gaussian': #see_sig = float(header['SEE_SIG']) #sigma value of gaussian fit to do the #see_sig= sdss_scale_factor*see_sig see_sig = pix_width #see_kernel = conv.Gaussian1DKernel(see_sig, x_size = int(slit_width), mode = 'oversample') if int(kernel_width) % 2 == 0: kernel_width = kernel_width + 1 else: pass see_kernel = conv.Gaussian1DKernel(see_sig, x_size=int(kernel_width), mode='oversample') see_kernel.normalize() spec_conv = conv.convolve(fluxes, see_kernel) elif kernel_type == 'sdss_match': see_sig = float( header['SEE_SIG']) #sigma value of gaussian fit to do the conv_see_sig = np.sqrt(see_sig**2 - sdss_see_sig**2) print('sdss_see_sig', sdss_see_sig) print('see_sig', see_sig) print('conv_see_sig', conv_see_sig) #see_sig= sdss_scale_factor*see_sig conv_see_sig = conv_see_sig * sdss_scale_factor #see_kernel = conv.Gaussian1DKernel(see_sig, mode = 'oversample') see_kernel = conv.Gaussian1DKernel(conv_see_sig, mode='oversample') see_kernel.normalize() spec_conv = conv.convolve(fluxes, see_kernel) pix_kernel = conv.Box1DKernel(width=int(sdss_scale_factor * pix_width), mode='oversample') pix_kernel.normalize() spec_conv = conv.convolve(spec_conv, pix_kernel) elif kernel_type == 'box': pix_kernel = conv.Box1DKernel(width=int(pix_width), mode='oversample') pix_kernel.normalize() spec_conv = conv.convolve(fluxes, pix_kernel) else: print('something wrong with convolution attempt') pass spec_out = np.vstack([wavelengths, spec_conv]) return spec_out
def mkolam(lam, dlsf, dfiblam, ofile, filfile, abmag): # Returns object "ofile" spectrum for a given LSF FWHM, and slit width. # The result is sampled in wavelength at the instrument pixel dispersion # Result does not include slitlosses. Normalized to ABmag in filter in "filfile" c = 2.99792458e18 # Speed of light in [A/s] data = ascii.read(ofile, names=['col1', 'col2']) lam0 = data['col1'] olam0 = data['col2'] # interpolate to regular grid (finer between original file grid and lam) ddisp0 = np.amin([ np.median(lam0[1:len(lam0) - 1] - lam0[0:len(lam0) - 2]), np.median(lam[1:len(lam) - 1] - lam[0:len(lam) - 2]) ]) lam1 = np.arange(np.amin(lam0), np.amax(lam0), ddisp0) f = interp1d(lam0, olam0, fill_value='extrapolate') olam1 = f(lam1) # convolve with LSF (Gaussian of FWHM=dlsf) gauss = conv.Gaussian1DKernel(stddev=dlsf / 2.355 / ddisp0, x_size=round_up_to_odd(10 * dlsf / 2.355 / ddisp0)) olam2 = conv.convolve(olam1, gauss.array, boundary='extend') # convolve with fiber profile (Gaussian with FWHM=dfiblam) gauss = conv.Gaussian1DKernel(stddev=dfiblam / 2.355 / ddisp0, x_size=round_up_to_odd(10 * dfiblam / 2.355 / ddisp0)) olam3 = conv.convolve(olam2, gauss.array, boundary='extend') # read filter curve and interpolate to object lambda grid datafil = ascii.read(filfile, names=['col1', 'col2']) lamfil0 = datafil['col1'] tfil0 = datafil['col2'] f = interp1d(lamfil0, tfil0, fill_value='extrapolate') tfil1 = f(lam1) tfil1[lam1 <= lamfil0.min()] = 0 tfil1[lam1 >= lamfil0.max()] = 0 lameff = np.trapz(lam1 * tfil1 * lam1, lam1) / np.trapz(tfil1 * lam1, lam1) # normalize to ABmag in filter "filfile" monoflam0 = np.trapz(olam3 * tfil1 * lam1, lam1) / np.trapz( tfil1 * lam1, lam1) monoflam1 = 10.0**(-0.4 * (abmag + 48.6)) * c / lameff**2 olam4 = olam3 * monoflam1 / monoflam0 logf.write(str(monoflam0) + '\n') logf.write(str(monoflam1) + '\n') logf.write(str(np.mean(olam1)) + '\n') logf.write(str(np.mean(olam2)) + '\n') logf.write(str(np.mean(olam3)) + '\n') logf.write(str(np.mean(olam4)) + '\n') # interpolate to lam f = interp1d(lam1, olam4, fill_value='extrapolate') return f(lam)
def __init__( self, grid_size, beam_maj_au=None, beam_min_au=None, vreso_kms=None, beam_pa_deg=0, mode="fft", ): # relation : standard deviation = 1/(2 sqrt(ln(2))) * FWHM of Gaussian # theta_deg : cclw is positive self.mode = mode sigma_over_FWHM = 2 * np.sqrt(2 * np.log(2)) conv_size = [beam_maj_au + 1e-100, beam_min_au + 1e-100] if vreso_kms is not None: conv_size += [vreso_kms + 1e-100] stddev = np.array(conv_size) / np.array(grid_size) / sigma_over_FWHM beampa = np.radians(beam_pa_deg) self.Kernel_xy2d = aconv.Gaussian2DKernel( x_stddev=stddev[0], y_stddev=stddev[1], theta=beampa )._array if len(conv_size) == 3 and (conv_size[2] is not None): Kernel_v1d = aconv.Gaussian1DKernel(stddev[2])._array self.Kernel_3d = np.multiply( # self.Kernel_xy2d[np.newaxis, :, :], self.Kernel_xy2d[:, :, np.newaxis], Kernel_v1d[np.newaxis, np.newaxis, :], )
def test_smooth_gaussian_good(simulated_spectra, stddev): """ Test Gaussian1DKernel smoothing with correct parmaeters. Standard deviation values need to be a number greater than 0. """ # Create the spectrum spec1 = simulated_spectra.s1_um_mJy_e1 flux_original = spec1.flux # Calculate the smoothed flux using Astropy gaussian_kernel = convolution.Gaussian1DKernel(stddev) flux_smoothed_astropy = convolution.convolve(flux_original, gaussian_kernel) # Test gaussian smoothing spec1_smoothed = gaussian_smooth(spec1, stddev) compare_flux(spec1_smoothed.flux.value, flux_smoothed_astropy, flux_original.value, rtol=0.02) # Check the input and output units assert spec1.wavelength.unit == spec1_smoothed.wavelength.unit assert spec1.flux.unit == spec1_smoothed.flux.unit assert len(spec1.meta) == len(spec1_smoothed.meta)
def plot_start(self): """ Plot starting point for peakbag Plots the starting model to be used in peakbag as a diagnotstic. """ dnu = 10**np.median(self.start_samples, axis=0)[0] xlim = [min(self.f[self.sel]) - dnu, max(self.f[self.sel]) + dnu] fig, ax = plt.subplots(figsize=[16, 9]) ax.plot(self.f, self.s, 'k-', label='Data', alpha=0.2) smoo = dnu * 0.005 / (self.f[1] - self.f[0]) kernel = conv.Gaussian1DKernel(stddev=smoo) smoothed = conv.convolve(self.s, kernel) ax.plot(self.f, smoothed, 'k-', label='Smoothed', lw=3, alpha=0.6) ax.plot(self.f[self.sel], self.model(self.start_samples.mean(axis=0)), 'r-', label='Start model', alpha=0.7) ax.set_ylim([0, smoothed.max() * 1.5]) ax.set_xlim(xlim) ax.set_xlabel(r'Frequency ($\mu \rm Hz$)') ax.set_ylabel(r'SNR') ax.legend() return fig
def convolve_flux(flux, kernel=convolution.Gaussian1DKernel(stddev=7)): """Perform convolution with kernel of spectrum's fluxes. Default is Gaussian kernel with standard deviation of value 7. """ # TODO write a test return convolution.convolve(flux, kernel, boundary='extend')
def mklinelam(lam, dlsf, dfiblam, linelam, lineflux, linefwhm): instsigma=np.sqrt(dlsf**2+dfiblam**2)/2.355 # rough estimate of instrumental sigma sigma=np.max([linefwhm/2.355, instsigma/2]) # set floor of line width to half instrumental to avoid sampling problems linelam1=lineflux/(np.sqrt(2*np.pi)*sigma)*np.exp(-1*(lam-linelam)**2/(2*sigma**2)) # convolve with LSF (Gaussian of FWHM=dlsf) ddisp0=np.median(lam[1:len(lam)-1]-lam[0:len(lam)-2]) gauss=conv.Gaussian1DKernel(stddev=dlsf/2.355/ddisp0, x_size=round_up_to_odd(10*dlsf/2.355/ddisp0)) linelam2=conv.convolve(linelam1, gauss.array, boundary='extend') # convolve with fiber profile (Gaussian with FWHM=dfiblam) gauss=conv.Gaussian1DKernel(stddev=dfiblam/2.355/ddisp0, x_size=round_up_to_odd(10*dfiblam/2.355/ddisp0)) linelam3=conv.convolve(linelam2, gauss.array, boundary='extend') # debugging GB # mysel=(lam>6550)*(lam<6570) # ascii.write([lam[mysel], linelam1[mysel], linelam2[mysel], linelam3[mysel]], tmpdir+'/junk2.dat', overwrite=True) # ascii.write([np.array([linefwhm, sigma, linelam, lineflux, np.sum(linelam1)])], tmpdir+'/junk3.dat', overwrite=True) return linelam3
def gaussian_smooth(spectrum, stddev): """ Smooth a `~specutils.Spectrum1D` instance based on a `astropy.convolution.Gaussian1DKernel`. Parameters ---------- spectrum : `~specutils.Spectrum1D` The spectrum object to which the smoothing will be applied. stddev : number The stddev of the kernel, in pixels, as defined in `astropy.convolution.Gaussian1DKernel` Returns ------- spectrum : `~specutils.Spectrum1D` Output `~specutils.Spectrum1D` which is copy of the one passed in with the updated flux. Raises ------ ValueError In the case that ``stddev`` is not the correct type or value. """ # Parameter checks if not isinstance(stddev, (int, float)) or stddev <= 0: raise ValueError('The stddev parameter, {}, must be a number greater than 0'.format( stddev)) # Create the gaussian kernel gaussian_kernel = convolution.Gaussian1DKernel(stddev) # Call and return the convolution smoothing. return convolution_smooth(spectrum, gaussian_kernel)
def plot_flat_fit(self, thin=10, alpha=0.2): ''' Plots the result of the fit in model space but without the horrible ladder of plot_fit. ''' n = self.ladder_p.shape[0] fig, ax = plt.subplots(figsize=[16, 9]) ax.plot(self.f, self.snr, 'k-', label='Data', alpha=0.2) dnu = 10**self.asy_result['summary'].loc['mean'].dnu numax = 10**self.asy_result['summary'].loc['mean'].numax smoo = dnu * 0.005 / (self.f[1] - self.f[0]) kernel = conv.Gaussian1DKernel(stddev=smoo) smoothed = conv.convolve(self.snr, kernel) ax.plot(self.f, smoothed, 'k-', label='Smoothed', lw=3, alpha=0.6) for i in range(n): for j in range(0, len(self.samples), thin): mod = self.model(self.samples['l0'][j], self.samples['l2'][j], self.samples['width0'][j], self.samples['width2'][j], self.samples['height0'][j], self.samples['height2'][j], self.samples['back'][j]) ax.plot(self.ladder_f[i, :], mod[i, :], c='r', alpha=alpha) ax.set_ylim([0, smoothed.max() * 1.5]) ax.set_xlim([ max([self.f.min(), numax - (n + 2) / 2 * dnu]), min([numax + (n + 2) / 2 * dnu, self.f.max()]) ]) #ax.set_xlim([self.f.min(), self.f.max()]) ax.set_xlabel(r'Frequency ($\mu \rm Hz$)') ax.set_ylabel(r'SNR') ax.legend(loc=1) return fig
def test_spectral_smooth(data_522_delta, use_dask): cube, data = cube_and_raw(data_522_delta, use_dask=use_dask) result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0), use_memmap=False) np.testing.assert_almost_equal( result[:, 0, 0].value, convolution.Gaussian1DKernel(1.0, x_size=5).array, 4) result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0), use_memmap=True) np.testing.assert_almost_equal( result[:, 0, 0].value, convolution.Gaussian1DKernel(1.0, x_size=5).array, 4)
def test_fittheory_convolved(self): """ Test the fitting of the available analytical functions with convolution enabled """ testspec = generate_cdespectrum() testspec1 = testspec.subspectrum(2000., 2300., clone=True) testpsf1 = convolution.Gaussian1DKernel(5) testfitter1 = Fitter.fromspectrum(testspec1, psf=testpsf1) testpars = Parameters() # (Name, Value, Vary, Min, Max, Expr) testpars.add_many(('lor1', 1.67, False, None, None, None), ('lor2', 195., False, None, None, None), ('lor3', 1.5, False, None, None, None), ('peak', 0.05, True, 0.0, 0.1, None), ('pos', 2139.9, True, 2129.9, 2149.9, None)) testfitter1.add_analytical('cde_lorentzian', testpars, funcname='test lorentzian') testfitter1.perform_fit() testspec2 = testspec.subspectrum(2500., 3700., clone=True) testpsf2 = convolution.Gaussian1DKernel(5) testfitter2 = Fitter.fromspectrum(testspec2, psf=testpsf2) testpars = Parameters() # (Name, Value, Vary, Min, Max, Expr) testpars.add_many(('H', 1.0, True, 0.0, None, None), ('xR', 3000., True, 3000. - 50., 3000. + 50., None), ('w', 50.0, True, 0.0, None, None), ('tau', 50.0, True, 0.0, None, None)) testfitter2.add_analytical('flipped_egh', testpars, funcname='test fEGH') testfitter2.perform_fit() testfitter3 = Fitter.fromspectrum(testspec2, psf=testpsf2) testpars = Parameters() # (Name, Value, Vary, Min, Max, Expr) testpars.add_many( ('peak', 1.0, True, 0.0, None, None), ('pos', 3000., True, 3000. - 200., 3000. + 200., None), ('fwhm', 50.0, True, 0.0, None, None), ) testfitter3.add_analytical('gaussian', testpars, funcname='test gaussian') testfitter3.perform_fit()
def degrade_resolution(flux, disp_in, disp_out): ''' Convolve spectrum with a 1D gaussian kernel to degrade dispersion from disp_in to disp_out ''' fwhm = math.sqrt(disp_out**2 - disp_in**2) stddev = fwhm / (2. * math.sqrt(2. * math.log(2.))) gauss_kernel = convolution.Gaussian1DKernel(stddev=stddev) degraded_flux = convolution.convolve(flux, gauss_kernel) return degraded_flux
def get_delta_wave(wave, wave_gpm, frac_spec_med_filter=0.03): r""" Compute the change in wavelength per pixel. Given an input wavelength vector and an input good pixel mask, the *raw* change in wavelength is defined to be ``delta_wave[i] = wave[i+1]-wave[i]``, with ``delta_wave[-1] = delta_wave[-2]`` to force ``wave`` and ``delta_wave`` to have the same length. The method imposes a smoothness on the change in wavelength by (1) running a median filter over the raw values and (2) smoothing ``delta_wave`` with a Gaussian kernel. The boxsize for the median filter is set by ``frac_spec_med_filter``, and the :math:`\sigma` for the Gaussian kernel is either a 10th of that boxsize or 3 pixels (whichever is larger). Parameters ---------- wave : float `numpy.ndarray`_, shape = (nspec,) Array of input wavelengths. Must be 1D. wave_gpm : bool `numpy.ndarray`_, shape = (nspec) Boolean good-pixel mask defining where the ``wave`` values are good. frac_spec_med_filter : :obj:`float`, optional Fraction of the length of the wavelength vector to use to median filter the raw change in wavelength, used to impose a smoothness. Default is 0.03, which means the boxsize for the running median filter will be approximately ``0.03*nspec`` (forced to be an odd number of pixels). Returns ------- delta_wave : `numpy.ndarray`_, float, shape = (nspec,) A smooth estimate for the change in wavelength for each pixel in the input wavelength vector. """ # Check input if wave.ndim != 1: msgs.error('Input wavelength array must be 1D.') nspec = wave.size # This needs to be an odd number nspec_med_filter = 2 * int(np.round( nspec * frac_spec_med_filter / 2.0)) + 1 delta_wave = np.zeros_like(wave) wave_diff = np.diff(wave[wave_gpm]) wave_diff = np.append(wave_diff, wave_diff[-1]) wave_diff_filt = utils.fast_running_median(wave_diff, nspec_med_filter) # Smooth with a Gaussian kernel sig_res = np.fmax(nspec_med_filter / 10.0, 3.0) gauss_kernel = convolution.Gaussian1DKernel(sig_res) wave_diff_smooth = convolution.convolve(wave_diff_filt, gauss_kernel, boundary='extend') delta_wave[wave_gpm] = wave_diff_smooth return delta_wave
def test_spectral_smooth_fail(data_522_delta_beams, use_dask): cube, data = cube_and_raw(data_522_delta_beams, use_dask=use_dask) with pytest.raises(AttributeError, match=("VaryingResolutionSpectralCubes can't be " "spectrally smoothed. Convolve to a " "common resolution with `convolve_to` before " "attempting spectral smoothed.")): cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0))
def test_catch_kernel_with_units(data_522_delta, use_dask): # Passing a kernel with a unit should raise a u.UnitsError cube, data = cube_and_raw(data_522_delta, use_dask=use_dask) with pytest.raises( u.UnitsError, match="The convolution kernel should be defined without a unit."): cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0 * u.one), use_memmap=False)
def test_spectral_smooth_fail(): cube, data = cube_and_raw('522_delta_beams.fits') with pytest.raises(AttributeError) as exc: cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0)) assert exc.value.args[0] == ("VaryingResolutionSpectralCubes can't be " "spectrally smoothed. Convolve to a " "common resolution with `convolve_to` before " "attempting spectral smoothed.")
def test_catch_kernel_with_units(): # Passing a kernel with a unit should raise a u.UnitsError cube, data = cube_and_raw('522_delta.fits') with pytest.raises(u.UnitsError) as exc: result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel( 1.0 * u.dimensionless_unscaled), use_memmap=False) assert exc.value.args[ 0] == "The convolution kernel should be defined without a unit."
def mklinelam(lam, dlsf, dslitlam, linelam, lineflux, linefwhm): instsigma=np.sqrt(dlsf**2+dslitlam**2)/2.355 # rough estimate of instrumental sigma sigma=np.max([linefwhm/2.355, instsigma/2]) # set floor of line width to half instrumental to avoid sampling problems linelam1=lineflux/(np.sqrt(2)*sigma)*np.exp(-1*(lam-linelam)**2/(2*sigma**2)) # convolve with LSF (Gaussian of FWHM=dlsf) ddisp0=np.median(lam[1:len(lam)-1]-lam[0:len(lam)-2]) gauss=conv.Gaussian1DKernel(stddev=dlsf/2.355/ddisp0, x_size=round_up_to_odd(10*dlsf/2.355/ddisp0)) linelam2=conv.convolve(linelam1, gauss.array, boundary='extend') # convolve with slit (Top Hat of width=dslit) box=conv.Box1DKernel(dslitlam/ddisp0) linelam3=conv.convolve(linelam2, box.array, boundary='extend') return linelam3
def test_spectral_smooth_4cores(): pytest.importorskip('joblib') cube, data = cube_and_raw('522_delta.fits') result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0), num_cores=4, use_memmap=True) np.testing.assert_almost_equal( result[:, 0, 0].value, convolution.Gaussian1DKernel(1.0, x_size=5).array, 4) # this is one way to test non-parallel mode result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0), num_cores=4, use_memmap=False) np.testing.assert_almost_equal( result[:, 0, 0].value, convolution.Gaussian1DKernel(1.0, x_size=5).array, 4) # num_cores = 4 is a contradiction with parallel=False, but we want to make # sure it does the same thing result = cube.spectral_smooth(kernel=convolution.Gaussian1DKernel(1.0), num_cores=4, parallel=False) np.testing.assert_almost_equal( result[:, 0, 0].value, convolution.Gaussian1DKernel(1.0, x_size=5).array, 4)
def gconvolve(self, fwhm, **kwargs): """ gconvolve(fwhm,**kwargs) Convolve spectrum using a gaussian of given fwhm. Parameters ---------- fwhm : `float` The desired fwhm of the gaussian, in units of x axis. **kwargs : Arguments, optional This can be used to pass additional arguments to `convolve`. """ gkernel = convolution.Gaussian1DKernel(fwhm) self.convolve(gkernel, **kwargs)
def convolve_lsf(self, plot=False): '''Convolve with Line Spread Function''' # TODO: interpolate to velocity-grid before convolving # to make sure we have linear spacing print() print("--------------------Convolution with LSF--------------------") # what if the input is not linear in wavelength? # should we interpolate on the output grid first? delta_wave = np.mean(self.wavelen[1:] - self.wavelen[:-1]) deltav = const.c * delta_wave / np.mean(self.wavelen) # FWHM=3km/s, see wikipedia.org/wiki/Gaussian_function stddev = 3. * u.km / u.s / (2. * np.sqrt(2. * np.log(2.))) stddev /= deltav stddev = stddev.to(u.dimensionless_unscaled) if self.verbose: print("step in wavelen:", delta_wave) print("step in velocity:", deltav) print(" => stddev =", stddev, "pixel") gauss = ac.Gaussian1DKernel(stddev) for i_x in range(self.target_cube.shape[2]): #print(self.target_cube.shape[2]-i_x, end=' ', flush=True) if i_x % 2 == 0: print("\r ", i_x * 100 // (self.target_cube.shape[2]-1), end='% \r', flush=True) for i_y in range(self.target_cube.shape[1]): self.target_cube[:, i_y, i_x] = ac.convolve_fft( self.target_cube[:, i_y, i_x], gauss, boundary='wrap') print(" ", end='\r') if plot: plt.plot(self.wavelen, self.target_cube[:, self.plotpix[0], self.plotpix[1]]) plt.title("Pixel [" + str(self.plotpix[0]) + "," + str(self.plotpix[1]) + "] after convolution with LSF") plt.xlabel("Wavelength [micron]") plt.ylabel("Flux [Jy/arcsec2]") plt.show()
def plot_start(self): ''' Plots the starting model as a diagnotstic. ''' fig, ax = plt.subplots(figsize=[16,9]) ax.plot(self.f, self.s, 'k-', label='Data', alpha=0.2) smoo = self.start[0] * 0.005 / (self.f[1] - self.f[0]) kernel = conv.Gaussian1DKernel(stddev=smoo) smoothed = conv.convolve(self.s, kernel) ax.plot(self.f, smoothed, 'k-', label='Smoothed', lw=3, alpha=0.6) ax.plot(self.f[self.sel], self.model(self.start_samples.mean(axis=0)), 'r-', label='Start model', alpha=0.7) ax.set_ylim([0, smoothed.max()*1.5]) ax.set_xlabel(r'Frequency ($\mu \rm Hz$)') ax.set_ylabel(r'SNR') ax.legend() return fig
def calc_moments(mol='NH3_11'): if mol == 'CS': rms = 320 * u.mK else: rms = 120 * u.mK v_lo = 83.0 * u.km / u.s v_hi = 90.0 * u.km / u.s # FIXME filep = PDir.map_name('G285_mosaic', 'NH3_11') cube = read_cube(filep) beam = radio_beam.Beam.from_fits_header(cube.header) cube = cube.spectral_slab(v_lo, v_hi) cube = cube.spectral_smooth(convolution.Gaussian1DKernel(4 / 2.355)) spax = cube.spectral_axis # smooth in area and velocity, create mask bigger_beam = radio_beam.Beam(major=2 * beam.major, minor=2 * beam.minor, pa=beam.pa) cube_s = cube.convolve_to(bigger_beam) # calculate moments filen_fmt = 'data/test_imaging/test_gbt_moments/G285_mosaic_gbt_NH3_11_{0}.fits' mom0 = cube.with_mask(cube_s > 1 * rms).moment(order=0) write_cube(mom0, PDir.IMG / Path(filen_fmt.format('mom0'))) mom1 = cube.with_mask(cube_s > 2 * rms).moment(order=1) write_cube(mom1, PDir.IMG / Path(filen_fmt.format('mom1'))) mom2 = cube.with_mask(cube_s > 2 * rms).moment(order=2) write_cube(mom2, PDir.IMG / Path(filen_fmt.format('mom2'))) mom3 = cube.with_mask(cube_s > 2 * rms).moment(order=3) write_cube(mom3, PDir.IMG / Path(filen_fmt.format('mom3'))) momS = cube.with_mask(cube_s > 2 * rms).linewidth_sigma() write_cube(momS, PDir.IMG / Path(filen_fmt.format('sigma'))) momM = cube.with_mask(cube_s > 1 * rms).max(axis=0) write_cube(momM, PDir.IMG / Path(filen_fmt.format('max'))) momV = cube.with_mask(cube_s > 2 * rms).argmax(axis=0).astype(float) momV[momV == 0] = np.nan chans = np.unique(momV) chans = chans[~np.isnan(chans)] for ix in chans: momV[momV == ix] = spax[int(ix)].value momV = spectral_cube.lower_dimensional_structures.Projection(momV, wcs=mom0.wcs) write_cube(momV, PDir.IMG / Path(filen_fmt.format('vmax')))
def specsmooth_to_vla(): #for target in ('G28539',): # for mol in ('NH3_11',): for target in TARGETS: for mol in ('NH3_11', 'NH3_22'): print(f'-- Smoothing cube for {target}_{mol}') gbt_filep = PDir.gbt_map_name(target, mol, modif='all_conv') gbt_c = read_cube(gbt_filep) # need the VLA cube to get the precise spectral axis to interpolate onto vla_filep = PDir.vla_map_name(target, mol.lower(), ext='image.fits') vla_c = read_cube(vla_filep) gbt_res = calc_velo_res(gbt_c) vla_res = calc_velo_res(vla_c) kernel_width = ((vla_res**2 - gbt_res**2)**(0.5) / gbt_res / FWHM).to('') kernel = convolution.Gaussian1DKernel(kernel_width) smooth_c = gbt_c.spectral_smooth(kernel) interp_c = smooth_c.spectral_interpolate( vla_c.spectral_axis, suppress_smooth_warning=True) outp = PDir.gbt_map_name(target, mol, modif='vavg') write_cube(interp_c, outp)
def convolveLSF(rays, binsize, std, weights=None, plot=False): """Convolve a gaussian with the LSF determined by histogramming the ray LSF std should be supplied as a distance in mm""" #Bin up rays in dispersion direction n,b = np.histogram(rays[2],bins=\ np.arange(rays[2].mean()-.5,rays[2].mean()+.5,binsize),\ weights=weights) b = np.array([np.mean([b[i], b[i + 1]]) for i in range(len(b) - 1)]) #Create convolution kernel gaussk = conv.Gaussian1DKernel(std / binsize) n2 = conv.convolve(n, gaussk) #Determine FWHM maxi = np.argmax(n2) #Index of maximum value #Find positive bound bp = b[maxi:] fwhmp = bp[np.argmin(np.abs(n2[maxi:] - n2.max() / 2))] - b[maxi] bm = b[:maxi] fwhmm = b[maxi] - bm[np.argmin(np.abs(n2[:maxi] - n2.max() / 2))] if plot is True: plt.plot(b, n) plt.plot(b, n2) return fwhmm + fwhmp
def plot(self, thin=100): ''' Plots the data and some models generated from the samples from the posteriod distribution. Parameters ---------- thin: int Thins the samples of the posterior in order to speed up plotting. Returns ------- fig: Figure The figure element containing the plots. ''' fig, ax = plt.subplots(figsize=[16,9]) ax.plot(self.f, self.s, 'k-', label='Data', alpha=0.2) smoo = self.start[0] * 0.005 / (self.f[1] - self.f[0]) kernel = conv.Gaussian1DKernel(stddev=smoo) smoothed = conv.convolve(self.s, kernel) ax.plot(self.f, smoothed, 'k-', label='Smoothed', lw=3, alpha=0.6) ax.plot(self.f[self.sel], self.model(self.flatchain[0, :]), 'r-', label='Model', alpha=0.2) for i in np.arange(thin, len(self.flatchain), thin): ax.plot(self.f[self.sel], self.model(self.flatchain[i, :]), 'r-', alpha=0.2) freqs = self.modeID['nu_med'] for f in freqs: ax.axvline(f, c='k', linestyle='--') ax.set_ylim([0, smoothed.max()*1.5]) ax.set_xlim([self.f[self.sel].min(), self.f[self.sel].max()]) ax.set_xlabel(r'Frequency ($\mu \rm Hz$)') ax.set_ylabel(r'SNR') ax.legend(loc=1) return fig