def specflat(flat,rows=True,indiv=False,wid=100) : """ Removes spectral signature from a flat by dividing by smoothed version Args: flat: input flat fields Keyword args: rows (bool) : specifies if smoothing is along rows (default), otherwise columns indiv (bool) : specifies if smoothing is done row-by-row, or single for whole image (default) wid (int) : boxcar kernel width (default=100) Returns: flat with spectral signature removed """ boxcar = Box1DKernel(wid) smooth=flat if rows : if indiv : for row in range(flat.shape[0]) : smooth[row,:] /= convolve(flat[row,:],boxcar,boundary='extend') else : c=convolve(flat.sum(axis=0),boxcar,boundary='extend') for row in range(flat.shape[0]) : smooth[row,:] /= c else : print('smoothing by columns not yet implemented!') pdb.set_trace() return smooth
def calculate_gradient(self,P,G,Z,smooth=False): """Calculate the gradient of any property. Deals with grid points that have no mass (that should'nt contribute to the gradient). :param P: A param.Param instance. .. warning:: This returns the gradient of the input field ... kind of ... sometimes """ Z = ma.masked_where(G.m<P.M_tol,Z).reshape(P.G.ny,P.G.nx) # if smooth: # For details of astropy convolution process, see here: http://docs.astropy.org/en/stable/convolution/using.html # kernel = Box2DKernel(smooth) # smallest possible square kernel is 3 # kernel = Gaussian2DKernel(x_stddev=1,y_stddev=1) # Z = convolve(Z, kernel, boundary='extend') dZdy,dZdx = gradient(Z,G.dy,G.dx) if smooth: # For details of astropy convolution process, see here: http://docs.astropy.org/en/stable/convolution/using.html # # kernel = Box2DKernel(smooth) # smallest possible square kernel is 3 kernel = Gaussian2DKernel(x_stddev=1,y_stddev=1) dZdy = convolve(dZdy, kernel, boundary='extend') dZdx = convolve(dZdx, kernel, boundary='extend') grad = array([dZdx.flatten(), dZdy.flatten(), zeros_like(G.m)]).T return grad
def process_image(medianed_image,vgridsize,hgridsize,lg,filter_width=13): # define your function for leastsq to obtain initial value estimates: def func(x): return k() + np.multiply(n(),np.absolute(x)) IV = np.zeros((vgridsize,2)) k = Parameter(5) n = Parameter(-1.5) for i in range(0,vgridsize): IV[i] = fit(func,[k,n],np.log10(medianed_image[i,:]),np.log10(np.abs(lg)))[0] #extrapolate power law data pl_image = np.zeros((vgridsize,hgridsize)) for i in range(0,vgridsize): k = Parameter(IV[i,0]) n = Parameter(IV[i,1]) pl_image[i] = (10**IV[i,0])*np.power(np.abs(lg),IV[i,1]) #detrending data and power law extrapolation using boxcar filtering data_filtered = np.zeros((vgridsize,hgridsize)) for i in range(0,vgridsize): data_filtered[i] = convolve(medianed_image[i,:],Box1DKernel(filter_width)) smooth_pl = np.zeros((vgridsize,hgridsize)) for i in range(0,vgridsize): smooth_pl[i] = convolve(pl_image[i,:],Box1DKernel(filter_width)) del i return data_filtered,pl_image,smooth_pl,IV
def convolve_with_psf(self, add_psf=True): if add_psf: if self.telescope.psf_fits_file != None: #first, rebin to psf pixel scale #n_pixel_orig = self.sunrise_image.n_pixels n_pixel_new = self.sunrise_image.n_pixels*self.sunrise_image.pixel_in_arcsec/self.telescope.psf_pixsize_arcsec new_image = congrid(self.sunrise_image.image, (n_pixel_new,n_pixel_new)) #second, convolve with PSF if CONVOLVE_TYPE=='astropy': #astropy.convolution.convolve() print "convolving with astropy" conv_im = convolve(new_image,self.telescope.psf_kernel/np.sum(self.telescope.psf_kernel),boundary='fill',fill_value=0.0) #boundary option? else: #scipy.signal.convolve2d() conv_im = convolve(new_image,self.telescope.psf_kernel/np.sum(self.telescope.psf_kernel),boundary='fill',fillvalue=0.0,mode='same') #boundary option? self.psf_image.init_image(conv_im,self) del new_image, conv_im else: self.add_gaussian_psf(add_psf=add_psf) else: self.psf_image.init_image(self.sunrise_image.image, self) gc.collect()
def match_psf(img, psf, psfto): """ match the psf of the image from psf to psfto Params ------ img (np 2d array) psf (np 2d array) psfto (np 2d array) Return ------ img_cnvled (np 2d array): the psf matched image psf_cnvled (np 2d array): the matched psf (psf convolved with kernel_cnvl) kernel_cnvl (np 2d array): the moffat kernel that can smear psf into psfto """ # get convolving kernel kernel_cnvl = get_convolving_moffat_kernel(psf, psfto) # make psf matched img img_cnvled = ac.convolve(img, kernel_cnvl) # make psf matched psf psf_cnvled = ac.convolve(psf, kernel_cnvl) return img_cnvled, psf_cnvled, kernel_cnvl
def test_mask_convolve(): # Numpy is fundamentally incompatible with the objects we have created. # np.ma.is_masked(array) checks specifically for the array's _mask # attribute. We would have to refactor deeply to correct this, and I # really don't want to do that because 'None' is a much more reasonable # and less dangerous default for a mask. test_wcs_1 = WCS(naxis=1) spec = OneDSpectrum(twelve_qty_1d, wcs=test_wcs_1) assert spec.mask is False from astropy.convolution import convolve,Box1DKernel convolve(spec, Box1DKernel(3))
def smoothing(parameters,gridvals): cellsize = parameters.boxsize/parameters.Ng smoothing_radius_cells = parameters.smoothing_radius/cellsize kernel_res = 3 kernel = make_kernel([kernel_res,kernel_res,kernel_res],smoothing_radius_cells) smoothed_vals = copy(gridvals) smoothed_vals = convolve(smoothed_vals,kernel,boundary='wrap') n = 0 while sp.any(sp.isnan(smoothed_vals)): smoothed_vals = convolve(smoothed_vals,kernel,boundary='wrap') print "Went through the convolving-loop", n, "times" return smoothed_vals
def convolveGaussian(self, image, gaussSigma, **kwargs): if (type(gaussSigma) is int) or (type(gaussSigma) is float): gaussSigma = np.array([gaussSigma, gaussSigma]) gRow = conv.Gaussian1DKernel(gaussSigma[0]) gCol = conv.Gaussian1DKernel(gaussSigma[1]) convImage = np.copy(image) for rowNum in range(0, len(image)): convImage[rowNum] = conv.convolve(convImage[rowNum], gRow, **kwargs) for col in range(0, len(image.T)): convImage[:,col] = conv.convolve(convImage[:,col], gCol, **kwargs) return convImage
def get_inflection_point(x, w=2, threshold=0.01): from astropy.convolution import convolve, Gaussian1DKernel sm = convolve(x, Gaussian1DKernel(w), boundary="extend") pos = np.diff(sm) > threshold return np.argmax(pos) return np.argmin(np.abs(np.diff(x)))
def timeseries(ax, telemetry, select=None, **kwargs): """Plot a telemetry timeseries.""" time, data = prepare_timeseries_data(telemetry) kwargs.setdefault('alpha', max([0.01, 5.0/data.shape[1]])) if data.shape[1] > 20: kwargs.setdefault('color', 'k') if select is not None: data = data[:,select] lines = ax.plot(time, data, **kwargs) if select is not None: sdata = np.apply_along_axis(lambda a: convolve(a, Gaussian1DKernel(stddev=50), boundary='extend'), 0, data) kwargs['alpha'] = 1.0 for i, line in enumerate(lines): kwargs['color'] = line.get_color() ax.plot(time, sdata[:,i], **kwargs) ax.set_xlabel("Time (s)") ax.set_ylabel("{0:s}".format(telemetry.kind.name)) ax.set_title("Timeseries of {0:s} from {1:s}".format( telemetry.kind.name, telemetry.dataset.title())) ax.set_xlim(np.min(time), np.max(time))
def smoothing(combo, targres, origfwhm, pixscale): """ Smooth the image to the targeted final angular resolution. Parameters ---------- combo : float array Combined image targres : float The HPBW of the smoothed image (in units of arcsecond) origfwhm : float The original HPBW of input image (in units of arcsecond) pixscale : float The pixscale of the input image (in units of arcsecond) Returns ------- combo : float array Smoothed image """ fwhm = np.sqrt(8*np.log(2)) kernel_size = ((targres/fwhm)**2-(hiresfwhm/fwhm)**2)**0.5 pixel_n = kernel_size/pixscale #smooth the image using gaussian 2d kernel gauss_kernel = Gaussian2DKernel(pixel_n) combo = convolve(combo, gauss_kernel,normalize_kernel=True) return combo
def gaussian(x,par,kernel=None): """ gaussian(x,par,kernel=None) An 1D Gaussian function, structured in a way that it can be given an lmfit Parameters instance as input. Parameters ---------- x : numpy.ndarray The x axis data of function. par : lmfit.parameter.Parameters The lmfit Parameters instance, which should contain the following: * peak - the peak height of the Gaussian * fwhm - the full width at half maximum of the Gaussian * pos - the peak position of the Gaussian kernel : Nonetype, numpy.ndarray or astropy.convolution.Kernel If set, the result will be convolved using this kernel. Returns ------- The function calculated over the range in x, and convolved with the kernel if one was given. """ peak=par['peak'].value fwhm=par['fwhm'].value pos=par['pos'].value out_y=peak*np.exp(-2.35*(x-pos)**2./fwhm**2.) if not(np.any(kernel)): return out_y else: return convolution.convolve(out_y,kernel)
def diffusion(self, wave, im): """Simulate UVIS's charge diffusion. Parameters ---------- wave : float The effective wavelength of the image. [micron] im : ndarray The image to process. Returns ------- newim : ndarray The processed image. Notes ----- Based on diffusion parameters from STScI Instrument Science Report 2008-014. """ from astropy.convolution import convolve w0 = [0.250, 0.810] # micron k0 = np.array([[[0.027, 0.111, 0.027], [0.111, 0.432, 0.111], [0.027, 0.111, 0.027]], [[0.002, 0.037, 0.002], [0.037, 0.844, 0.037], [0.002, 0.037, 0.002]]]) dk = (k0[1] - k0[0]) / (w0[1] - w0[0]) k = k0[0] + dk * (wave - w0[0]) k /= k.sum() return convolve(im, k, boundary='extend')
def conv(img): kernel_file=pyfits.open(root+kfile) kernel=kernel_file[0].data new=convolve(img,kernel) return new
def convolve(self, target_beam): """ Convolve *to* this rsolution beam = [bmaj, bmin, bpa] """ from lib_beamdeconv import deconvolve_ell, EllipticalGaussian2DKernel from astropy import convolution # if difference between beam is negligible <1%, skip - it mostly happens when beams are exactly the same beam = self.get_beam() if (np.abs((target_beam[0]/beam[0])-1) < 1e-2) and (np.abs((target_beam[1]/beam[1])-1) < 1e-2) and (np.abs(target_beam[2] - beam[2]) < 1): logging.debug('%s: do not convolve. Same beam.' % self.imagefile) return # first find beam to convolve with convolve_beam = deconvolve_ell(target_beam[0], target_beam[1], target_beam[2], beam[0], beam[1], beam[2]) if convolve_beam[0] is None: logging.error('Cannot deconvolve this beam.') sys.exit(1) logging.debug('%s: Convolve beam: %.3f" %.3f" (pa %.1f deg)' \ % (self.imagefile, convolve_beam[0]*3600, convolve_beam[1]*3600, convolve_beam[2])) # do convolution on data bmaj, bmin, bpa = convolve_beam assert abs(self.img_hdr['CDELT1']) == abs(self.img_hdr['CDELT2']) pixsize = abs(self.img_hdr['CDELT1']) fwhm2sigma = 1./np.sqrt(8.*np.log(2.)) gauss_kern = EllipticalGaussian2DKernel((bmaj*fwhm2sigma)/pixsize, (bmin*fwhm2sigma)/pixsize, (90+bpa)*np.pi/180.) # bmaj and bmin are in pixels self.img_data = convolution.convolve(self.img_data, gauss_kern, boundary=None) self.img_data *= (target_beam[0]*target_beam[1])/(beam[0]*beam[1]) # since we are in Jt/b we need to renormalise self.set_beam(target_beam) # update beam
def test__cross_correlation(self): self.wc.lamp = self.ccd.copy() self.wc.serial_binning = 1 x_axis = np.arange(0, 4060, 1) reference = np.zeros(4060) gaussian = models.Gaussian1D(stddev=2) for i in sorted(np.random.choice(x_axis, 30)): gaussian.mean.value = i reference += gaussian(x_axis) offset = np.random.choice(range(1, 15), 1)[0] for slit in [1, 2, 3, 4, 5]: new_array = np.append(reference[offset:], np.zeros(offset)) if slit > 3: box_kernel = Box1DKernel(width=slit / 0.15) new_array = convolve(new_array, box_kernel) self.assertEqual(len(reference), len(new_array)) self.wc.lamp.header['SLIT'] = '{:d}.0" long slit'.format(slit) correlation_value = self.wc._cross_correlation(reference=reference, new_array=new_array) self.assertEqual(correlation_value, offset)
def gsmooth_cube(cube, kernelsize, use_fft=True, psf_pad=False, fft_pad=False, kernelsize_mult=8, **kwargs): """ Smooth a cube with a gaussian in 3d Because even a tiny cube can become enormous if you have, say, a 1024x32x32 cube, padding is off by default """ if cube.ndim != 3: raise ValueError("Wrong number of dimensions for a data cube") #z,y,x = np.indices(cube.shape) # use an odd kernel size for non-fft, even kernel size for fft ks = (np.array(kernelsize)*kernelsize_mult).astype('int') if np.any(ks % 2 == 0) and not use_fft: ks[ks % 2 == 0] += 1 z,y,x = np.indices(ks) kernel = np.exp(-((x-x.max()/2.)**2 / (2.*(kernelsize[2])**2) + (y-y.max()/2.)**2 / (2.*(kernelsize[1])**2) + (z-z.max()/2.)**2 / (2.*(kernelsize[0])**2))) if use_fft: return convolve_fft(cube, kernel, normalize_kernel=True, psf_pad=psf_pad, fft_pad=fft_pad, **kwargs) else: return convolve(cube, kernel, normalize_kernel=True, **kwargs)
def voigt_abs(pars, t): """ f_obs = f_source * e ^-tau """ N, sigma, z, osc, l0, gamma, resolution_fwhm = pars # Move wavelength array to rest t = t.copy() / (1 + z) # Center wavlength array at line t_rest = t - l0 # Convert to km/s t = c * t_rest / t # Get optical depth tau = voigt_tau(t, N, osc, l0, sigma, gamma) # Absorb flux flux = np.exp(-tau) # Correct for instrumental resolution if resolution_fwhm > 0.: # Get transformation from km/s to pixels for convolution mask = (t > - 5000) & (t < 5000) transform = np.median(np.diff(t)[mask[:-1]]) if np.isnan(transform): transform = 1e3 # print(transform) # Convolve with linespread-function flux = convolve(flux, Gaussian1DKernel(stddev=resolution_fwhm/(sigfwhm*transform), mode="oversample")) return flux
def convolve_image(self,stddev,scale=True): # """The inputs are as follows: # stddev = standard deviation of the Gaussian the step function will be convolved with # scale = True -- will scale the flux by the redshift unless set to False # # The output variables are as follows: # Nothing is returned but the object property, img, is updated to hold the convolved image # """ ##CURRENTLY BUILDING IMAGE AS LAMBA,X,Y ##Because writing the fits file transposes the x and z axes for some reason self.img = np.zeros((len(self.wavelengths),len(self.frb[0,:]),len(self.frb[1,:]))) gauss = Gaussian1DKernel(stddev=stddev,x_size=len(self.wavelengths)) zconvolve = convolve(self.step_function,gauss.array,boundary='extend') for i in range(len(self.frb[0,:])): for j in range(len(self.frb[1,:])): if scale: self.img[:,j,i] = zconvolve*(self.frb[i,j]/((1.+self.z_observed)**4.0)) else: self.img[:,j,i] = zconvolve*self.frb[i,j] return
def run(self): while not self.kill_received: # get a task try: x_range, y_range = self.work_queue.get_nowait() except Queue.Empty: break # the actual processing print 'Worker running: ', multiprocessing.current_process() # print "Convolving image section - XRANGE=", y_range, " - YRANGE=", x_range im_size=np.asarray(shared_im.shape) kernel_size=np.asarray(shared_kernel.shape) im_pad=(kernel_size-1)/2+10 x_pad=[0 if x_range[0]==0 else -im_pad[0], 0 if x_range[1]==(im_size[0]-1) else im_pad[0]] y_pad=[0 if y_range[0]==0 else -im_pad[1], 0 if y_range[1]==(im_size[1]-1) else im_pad[1]] shared_nim[x_range[0]:x_range[1], y_range[0]:y_range[1]]=convolve(shared_im[x_range[0]+x_pad[0]:x_range[1]+x_pad[1], y_range[0]+y_pad[0]:y_range[1]+y_pad[1]], shared_kernel, normalize_kernel=True)[-x_pad[0]:x_range[1]-x_range[0]-x_pad[0], -y_pad[0]:y_range[1]-y_range[0]-y_pad[0]] print 'Worker done: ', multiprocessing.current_process() self.result_queue.put(id)
def calc_line_profile(self, phase, inclination, nbins=100, v_macro=2*u.km/u.s, v_inst=4*u.km/u.s, v_min=-40*u.km/u.s, v_max=40*u.km/u.s): # get CartesianRepresentation pointing to earth at these phases earth = set_earth(inclination, phase) # get CartesianRepresentation of projected velocities vproj = dot(earth, self.tile_velocities).to(u.km/u.s) # which tiles fall in which bin? bins = np.linspace(v_min, v_max, nbins) indices = np.digitize(vproj, bins) lum = self._luminosity_array(phase, inclination) phase = np.asarray(phase) trailed_spectrum = np.zeros((phase.size, nbins)) for i in range(nbins): mask = (indices == i) trailed_spectrum[:, i] = np.sum(lum*mask, axis=1) # convolve with instrumental and local line profiles # TODO: realistic Line Profile Treatment # For now we assume every element has same intrinsic # line profile bin_width = (v_max-v_min)/(nbins-1) profile_width_in_bins = np.sqrt(v_macro**2 + v_inst**2) / bin_width gauss_kernel = Gaussian1DKernel(stddev=profile_width_in_bins, mode='linear_interp') for i in range(phase.size): trailed_spectrum[i, :] = convolve(trailed_spectrum[i, :], gauss_kernel, boundary='extend') return bins, trailed_spectrum
def get_extrema(x, w=2, threshold=0.01): """ Return the valid range in pixels. This function tries to find the first local maximum and minimum and select the range between those. It can run into trouble if the first/last pixel are the min/max; most of the code is dedicated to these corner cases """ from astropy.convolution import convolve, Gaussian1DKernel sm = convolve(x, Gaussian1DKernel(w), boundary='extend') pos = np.diff(sm) > threshold # force first point to match second point # smoothing can affect edges if pos[0] != pos[1]: pos[0] = pos[1] if pos[0] != pos[2]: pos[:2] = pos[2] # Find the first point at which the slope is positive # (this is very near the 0/0 point) pospt = np.argmax(pos) if np.count_nonzero(pos) < 5+4: # implies there were no extrema found return 0,x.size elif pospt == 0: # find first *negative* extremum negpt = np.argmin(pos) pos[:negpt] = False pospt = np.argmax(pos) if pospt < negpt: pospt = pos.size - 1 return negpt,pospt else: return 0,pospt
def moment_masking(cube, kernel_size, clip=5, dilations=1): ''' ''' if not signal_id_flag: raise ImportError("signal-id is not installed." " This function is not available.") smooth_data = convolve(cube.filled_data[:], gauss_kern(kernel_size)) fake_mask = LazyMask(np.isfinite, cube=cube) smooth_cube = SpectralCube(data=smooth_data, wcs=cube.wcs, mask=fake_mask) smooth_scale = Noise(smooth_cube).scale mask = (smooth_cube > (clip * smooth_scale)).include() # Now dilate the mask once dilate_struct = nd.generate_binary_structure(3, 3) mask = nd.binary_dilation(mask, structure=dilate_struct, iterations=dilations) return mask
def resample(spectrum, resampled_header_broadcast, label_col=None, convolve=False, normalize=True): """Resamples the spectrum so that the x-axis starts at low and ends at high, while keeping the delta between the wavelengths""" resampled_header = resampled_header_broadcast.value if label_col is not None: logger.debug(spectrum.columns) without_label = spectrum.drop(label_col, axis=1) without_label.columns = pd.to_numeric(without_label.columns, errors="ignore") else: without_label = spectrum if convolve: to_interpolate = convolution.convolve(without_label.iloc[0].values, convolution.Gaussian1DKernel(7), boundary="extend") else: to_interpolate = without_label.iloc[0].values logger.debug(without_label) interpolated = np.interp(resampled_header, without_label.columns.values, to_interpolate) interpolated = interpolated[3:-3] # remove some weird artefacts that might happen because of convo/interpolation if normalize: interpolated = prep.minmax_scale([interpolated], axis=1) logger.debug("Interpolated:%s", interpolated) interpolated_df = pd.DataFrame(data=interpolated, columns=resampled_header[3:-3], index=spectrum.index.values) if label_col is not None: interpolated_df[label_col] = spectrum[label_col] return interpolated_df
def convolveSquaredGaussian(self, image, gaussSigma): if (type(gaussSigma) is int) or (type(gaussSigma) is float): gaussSigma = np.array([gaussSigma, gaussSigma]) gRow = conv.Gaussian1DKernel(gaussSigma[0]) gSqRow = conv.CustomKernel(np.power(gRow.array, 2)) gCol = conv.Gaussian1DKernel(gaussSigma[1]) gSqCol = conv.CustomKernel(np.power(gCol.array, 2)) convImage = np.copy(image) for rowNum in range(0, len(image)): convImage[rowNum] = conv.convolve(convImage[rowNum], gSqRow, boundary=None) for col in range(0, len(image.T)): convImage[:,col] = conv.convolve(convImage[:,col], gSqCol, boundary=None) return convImage
def mk_pix_stau(self, spec, kbin=22.*u.km/u.s, debug=False, **kwargs): """ Generate the smoothed tau array for kinematic tests Parameters ---------- spec: Spectrum1D class Input spectrum velo is expected to have been filled already fill: bool (True) Fill the dictionary with some items that other kin programs may need Returns ------- out_kin : dict Dictionary of kinematic measurements JXP on 11 Dec 2014 """ # Calcualte dv imn = np.argmin( np.fabs(spec.velo) ) dv = np.abs( spec.velo[imn] - spec.velo[imn+1] ) # Test for bad pixels pixmin = np.argmin( np.fabs( spec.velo-self.vmnx[0] ) ) pixmax = np.argmin( np.fabs( spec.velo-self.vmnx[1] ) ) pix = np.arange(pixmin, pixmax+1) npix = len(pix) badzero=np.where((spec.flux[pix] == 0) & (spec.sig[pix] <= 0))[0] if len(badzero) > 0: if np.max(badzero)-np.min(badzero) >= 5: raise ValueError('orig_kin: too many or too large sections of bad data') spec.flux[pix[badzero]] = np.mean(np.array([spec.flux[pix[np.min(badzero)-1]], spec.flux[pix[np.max(badzero)+1]]])) xdb.set_trace() # Should add sig too # Generate the tau array tau = np.zeros(npix) gd = np.where((spec.flux[pix] > spec.sig[pix]/2.) & (spec.sig[pix] > 0.) ) if len(gd) == 0: raise ValueError('orig_kin: Profile too saturated.') tau[gd] = np.log(1./spec.flux[pix[gd]]) sat = (pix == pix) sat[gd] = False tau[sat] = np.log(2./spec.sig[pix[sat]]) # Smooth nbin = (np.round(kbin/dv)).value kernel = Box1DKernel(nbin, mode='center') stau = convolve(tau, kernel, boundary='fill', fill_value=0.) if debug is True: xdb.xplot(spec.velo[pix], tau, stau) # Fill self.stau = stau self.pix = pix
def smooth(continuum, wo_continuum): total = wo_continuum + continuum g = Gaussian1DKernel(stddev=2) continuum = convolve(continuum, g, boundary='extend') wo_continuum = total - continuum return continuum, wo_continuum
def filter_direct(wavelength_range, image): # Make the Mexican hat kernel and convolve # The values given to the kernels should be 1.7328, 2.3963, 3.5270 # for S, M and L. mex = MexicanHat2DKernel(get_pixFWHM(wavelength_range)) mex_convol = convolve(image, mex, boundary = 'extend') return mex_convol
def convolve_images(): for image in input_images: hdulist = fits.open(input_images[image]) data = hdulist[2].data coords = [data.X_IMAGE, data.Y_IMAGE] convolved_image = 'g'+ input_images[image] outfile = convolve(coords, kernel) fits.writeto(convolved_image,np.array(outfile)) print np.shape(outfile)
def box_smooth(self, nbox, preserve=False, **kwargs): """ Box car smooth the spectrum Parameters ---------- nbox: int Number of pixels to smooth over preserve: bool (False) If True, perform a convolution to ensure the new spectrum has the same number of pixels as the original. **kwargs: dict If preserve=True, these keywords are passed on to astropy.convoution.convolve Returns ------- A new XSpectrum1D instance of the smoothed spectrum """ if preserve: from astropy.convolution import convolve, Box1DKernel new_fx = convolve(self.flux, Box1DKernel(nbox), **kwargs) new_sig = convolve(self.sig, Box1DKernel(nbox), **kwargs) new_wv = self.wavelength else: # Truncate arrays as need be npix = len(self.flux) try: new_npix = npix // nbox # New division except ZeroDivisionError: raise ZeroDivisionError('Dividing by zero..') orig_pix = np.arange(new_npix * nbox) # Rebin (mean) new_wv = liu.scipy_rebin(self.wavelength[orig_pix], new_npix) new_fx = liu.scipy_rebin(self.flux[orig_pix], new_npix) if self.sig_is_set: new_sig = liu.scipy_rebin( self.sig[orig_pix], new_npix) / np.sqrt(nbox) else: new_sig = None # Return return XSpectrum1D.from_tuple( (new_wv, new_fx, new_sig), meta=self.meta.copy())
def snrmap_fast(array, fwhm, nproc=None, plot=False, verbose=True): """ Serial implementation of the S/N map generation function. To be used as a quick proxy of the snrmap generated using the small samples statistics definition. Parameters ---------- array : array_like Input frame. fwhm : float Size in pixels of the FWHM. nproc : int or None Number of processes for parallel computing. plot : {False, True}, bool optional If True plots the SNR map. verbose: {True, False} Chooses whether to print results or not. Returns ------- snrmap : array_like Frame with the same size as the input frame with each pixel. """ if verbose: start_time = time_ini() if not array.ndim==2: raise TypeError('Input array is not a 2d array or image.') cy, cx = frame_center(array) tophat_kernel = Tophat2DKernel(fwhm/2.) array = convolve(array, tophat_kernel) sizey, sizex = array.shape snrmap = np.zeros_like(array) width = min(sizey,sizex)/2 - 1.5*fwhm mask = get_annulus(array, (fwhm/2)+1, width-1) mask = np.ma.make_mask(mask) yy, xx = np.where(mask) coords = [(x,y) for (x,y) in zip(xx,yy)] if nproc is None: nproc = int((cpu_count()/2)) # Hyper-threading doubles the # of cores if nproc==1: for y,x in zip(yy,xx): snrmap[y,x] = _snr_approx(array, (x,y), fwhm, cy, cx)[2] elif nproc>1: pool = Pool(processes=int(nproc)) res = pool.map(eval_func_tuple, itt.izip(itt.repeat(_snr_approx), itt.repeat(array), coords, itt.repeat(fwhm), itt.repeat(cy), itt.repeat(cx))) res = np.array(res) pool.close() yy = res[:,0] xx = res[:,1] snr = res[:,2] snrmap[yy.astype('int'), xx.astype('int')] = snr if plot: pp_subplots(snrmap, colorb=True, title='SNRmap') if verbose: print("S/N map created using {:} processes.".format(nproc)) timing(start_time) return snrmap
def SDR(x, y, prot, yerr=0, sep='peaks', retSD=True): """ Calculates the SDR of lightcurve data from any source. x = time data (days) y = (normalized) flux yerr = errors associated with fluxes (default value = 0) sep = 'dips' or 'peaks' """ dt = x - np.roll(x, 1) dt = dt[1:] ddt = np.median(dt) if np.isnan(ddt) == True: ddt = 0.1 width = int(np.round(prot / (ddt * 8))) if width == 0: width = 1 y = convolve(y, Box1DKernel(width), 'wrap') pwidth = 0.02 # peak width must be greater than Kepler cadence (30 mins) if sep == 'peaks': peaks = sig.find_peaks(y, width=pwidth, prominence=yerr)[0] elif sep == 'dips': peaks = sig.find_peaks(-y, width=pwidth, prominence=yerr)[0] xpeaks = [x[i] for i in peaks] ypeaks = [y[i] for i in peaks] psep = xpeaks - np.roll(xpeaks, 1) psep = psep[1:] psep = np.round(psep, 13) psep, counts = np.unique(psep, return_counts=True) if retSD == False: return xpeaks, ypeaks, psep, y elif retSD == True: tdb = 0 tsn = 0 if len(psep) > 0: for sep in psep: if sep > 0.8 * prot: tsn += 1 else: tdb += 1 #print(tsn,tdb) if tdb > 0 and tsn > 0: sdr = np.log10(tsn / tdb) if sdr > 2.0: sdr = 2.0 elif sdr < -2.0: sdr = -2.0 elif tdb == 0 and tsn != 0: sdr = 2.0 elif tsn == 0 and tdb != 0: sdr = -2.0 else: sdr = 0.0 return sdr else: raise Exception("retSD must be True or False")
channel = 40 print(vit[channel]) #import_donnees(simu, co=False, c18o=False, c16o=True) nom = "beta_12_rad_250" cont_co = lect_donnees(simu, nom, mol="co") cont_13 = lect_donnees(simu, nom, mol="13co") cont_18 = lect_donnees(simu, nom, mol="c18o") cont = cont_13 up, down = maxima(cont) gauss = Gaussian1DKernel(5) max_up, max_down = up[channel, :200], down[channel, :200] max_up, max_down = convolve( np.concatenate(([max_up[0]] * 10, max_up, [max_up[-1]] * 10)), gauss)[10:-10], convolve( np.concatenate( ([max_down[0]] * 10, max_down, [max_down[-1]] * 10)), gauss)[10:-10] t_1 = np.zeros(np.shape(cont[:, :, channel])) t_2 = np.zeros(np.shape(cont[:, :, channel])) for x in range(0, len(t_1[:, 0])): for y in range(0, len(t_1[0, :])): t_1[y, x], t_2[y, x] = sol(x - 201, y - 201, psi=psi) #fit des données avec "direct mapping ..." r, h, vit_reel = position(max_up, max_down, angle, vit[channel])
def sym_center(image,rmax): ''' finds the center of circular symmetry of a single image. INPUTS: image - image in the form of a 2D array rmax - the maximum radius you want it to check from a given center pixel for standard deviations when determining if that pixel is a good center or not. OUTPUTS: xc,yc - center of circular symmetry of the image ''' global xMax global yMax #smoothing before finding approximate center #helps avoid issues with cosmic rays gauss = conv.Gaussian2DKernel(stddev=6) new_im = conv.convolve(image, gauss) #find approximate center of image xMax = 0 yMax = 0 max_val = 0 for y in range(centerY-200,centerY+200): for x in range(centerX-200,centerX+200): if new_im[y][x] > max_val: xMax = x yMax = y max_val = new_im[y][x] #create 21 by 21 grid of values showing whether each possible pixel in the grid is a good center #lower values mean better center grid = np.zeros((21,21)) for y in range(21): print("starting row " + str(y)) for x in range(21): yc = yMax - (10) + y xc = xMax - (10) + x radii = make_radial_profile(image, xc, yc) for k in range(rmax+1): ids = np.where((radii>=k) & (radii<k+1)) for a in range(ids[0].shape[0]): ids[0][a] = ids[0][a] + yMax-50 for b in range(ids[1].shape[0]): ids[1][b] = ids[1][b] + xMax-50 sd = np.nanstd(image[ids]) grid[y][x] = grid[y][x] + sd/abs(np.nanmedian(image[ids])) print("created grid") #fitting a 2D gaussian to the grid to determine actual 'best' center maxval = np.nanmax(grid) data = grid*-1 data = data+maxval p = fitgaussian(data) xcc = p[2] ycc = p[1] print("grid centered at " + str(xcc)+","+str(ycc)) #converting position from small grid to actual image: xc = xMax - (21/2.-0.5) + xcc yc = yMax - (21/2.-0.5) + ycc print('Finishing sym_center; center of image is ' + str(xc)+","+str(yc)) return (xc, yc)
def ontype(self, event): zabs = np.double(0.) self.ax.draw_artist(self.ax) # when the user hits 'r': clear the axes and plot the original spectrum if event.key == 'r': self.ax.cla() self.ax.step(self.wave, self.flux, 'k-', linewidth=1) self.ax.set_xlabel('Wavelength') self.ax.set_ylabel('Flux') xr = [np.min(self.wave), np.max(self.wave)] yr = [np.min(self.flux), np.max(self.flux)] self.ax.set_ylim([yr[0], yr[1]]) self.ax.set_xlim([xr[0], xr[1]]) # Set top y max elif event.key == 't': xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() self.ax.set_ylim([ylim[0], event.ydata]) self.ax.set_xlim(xlim) plt.draw() elif event.key == 'Z': print('Testing to see if we can get a pop up window to work') self.set_redshift() self.DrawLineList(self.label) elif event.key == 'j': lambda_rest, LineList = self.identify_line_GUI() print(lambda_rest, LineList) self.zabs = (event.xdata - lambda_rest) / lambda_rest self.label = LineList self.DrawLineList(self.label) print('Target Redshfit set at : ' + np.str(self.zabs)) # Manage and plot multiple absorbers #Clunky GUI to plot lines elif event.key == 'K': self.manage_identified_absorbers() #Load a saved linelist elif event.key == '0': self.load_linelist_GUI() self.manage_identified_absorbers() #Load pre identified individual absorbers elif event.key == '+': #filename=self.read_identified_linelist_GUI() #print(filename) #self.plot_identified_linelist(filename) self.load_linelist_GUI() self.manage_identified_absorbers() self.fig.canvas.draw() plt.draw() # Set top y min elif event.key == 'b': xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() self.ax.set_ylim([event.ydata, ylim[1]]) self.ax.set_xlim(xlim) plt.draw() # Smooth spectrum elif event.key == 'S': self.vel[0] += 2 Filter_size = np.int(self.vel[0]) self.smoothed_spectrum = convolve( self.flux, Box1DKernel(Filter_size)) #medfilt(flux,np.int(Filter_size)) self.specplot() plt.draw() #Unsmooth Spectrum elif event.key == 'U': self.vel[0] -= 2 if self.vel[0] <= 0: self.vel[0] = 1 Filter_size = np.int(self.vel[0]) self.smoothed_spectrum = convolve( self.flux, Box1DKernel(Filter_size)) #medfilt(flux,np.int(Filter_size)) self.specplot() plt.draw() # Set X max elif event.key == 'X': xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() self.ax.set_xlim([xlim[0], event.xdata]) self.ax.set_ylim(ylim) plt.draw() # Set x min elif event.key == 'x': xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() self.ax.set_xlim([event.xdata, xlim[1]]) self.ax.set_ylim(ylim) plt.draw() # Set pan spectrum elif event.key == ']': xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() delx = (xlim[1] - xlim[0]) self.ax.set_xlim([xlim[1], xlim[1] + delx]) self.ax.set_ylim(ylim) plt.draw() # Set pan spectrum elif event.key == '[': xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() delx = (xlim[1] - xlim[0]) self.ax.set_xlim([xlim[0] - delx, xlim[0]]) self.ax.set_ylim(ylim) plt.draw() # Compute Equivalent Width between two points elif event.key == 'E': #ekeycounts +=1 self.lam_lim = np.append(self.lam_lim, event.xdata) self.lam_ylim = np.append(self.lam_ylim, event.ydata) # Keep running tab of all E clicks eclick = len(self.lam_lim) #self.specplot() self.ax.plot(event.xdata, event.ydata, 'rs', ms=5, picker=5, label='EW_pt', markeredgecolor='k') #self.fig.canvas.draw() if eclick == 2: # Check if the wave entries are monotonously increasing tab = self.lam_lim.argsort() EW, sig_EW, cont, wave_slice = self.compute_EW( self.wave / (1. + zabs), self.flux, self.lam_lim[tab], self.lam_ylim[tab], self.error) EW = np.array(EW) * 1000. sig_EW = np.array(sig_EW) * 1000. self.ax.plot(wave_slice, cont, 'r--') #ipdb.set_trace() print( '---------------------- Equivalent Width -------------------------------------' ) Wval = 'EW [mAA]: ' + '%.1f' % EW + ' +/- ' + '%.1f' % sig_EW self.ax.text(np.mean([self.lam_lim]), np.max(self.lam_ylim) + 0.2, Wval, rotation=90, verticalalignment='bottom') print(Wval) print( '---------------------------------------------------------------------------' ) self.lam_lim = [] self.lam_ylim = [] plt.draw() self.fig.canvas.draw() # Fit a Gaussian elif event.key == 'F': self.FXval = np.append(self.FXval, event.xdata) self.FYval = np.append(self.FYval, event.ydata) fclick = len(self.FXval) self.ax.plot(event.xdata, event.ydata, 'rs', ms=5, picker=5, label='EW_pt', markeredgecolor='k') self.fig.canvas.draw() plt.show() #Start Fitting if fclick == 3: # First fit a quick continuum qtq = np.where(((self.wave / (1. + zabs)) >= self.FXval[0]) & ((self.wave / (1. + zabs)) <= self.FXval[2])) ww = self.wave[qtq] / (1. + zabs) flux1 = self.flux[qtq] spline = splrep(np.append(self.FXval[0], self.FXval[2]), np.append(self.FYval[0], self.FYval[2]), k=1) continuum = splev(ww, spline) # Check if it is an absorption or emission line if ((self.FYval[1] < self.FYval[0]) & (self.FYval[1] < self.FYval[2])): ydata = 1. - (flux1 / continuum) gmodel = Model(gaussian) result = gmodel.fit(ydata, x=ww, amp=self.FYval[1] - self.FYval[1], cen=self.FXval[2], wid=0.5 * (self.FXval[2] - self.FXval[0])) Final_fit = (1. - result.best_fit) * continuum else: ydata = (flux1 / continuum) gmodel = Model(gaussian) result = gmodel.fit(ydata, x=ww, amp=self.FYval[1] - self.FYval[1], cen=self.FXval[2], wid=0.5 * (self.FXval[2] - self.FXval[0])) Final_fit = result.best_fit * continuum print(result.fit_report()) model_fit = self.ax.plot(ww, Final_fit, 'r-') plt.draw() print("Gaussian Fit") FXval = [] FYval = [] #If the user presses 'h': The help is printed on the screen elif event.key == 'h': print(''' --------------------------------------------------------------------------- This is an interactive 1D spectrum viewer. The help scene activates by pressing h on the plot. The program only works properly if none of the toolbar buttons in the figure is activated. It also needs pysimpleGUI code to be installed. https://pysimplegui.readthedocs.io/en/latest/ Useful Keystrokes: Keystrokes: r : Reset Spectrum and replot to default settings. h : Prints this help window. x or X : Set xmin, xmax b or t : Set ymin, ymax [ or ] : Pan left or right s or S. : Smooth or Unsmooth spectra E : Two E keystrokes will compute rest frame equivalent width at a defined region F : Three keystrokes to fit a Gaussian profile. [Currently not drawing on the spectrum] #GUI ELEMENTS [WARNING UNSTABLE] Works with TkAGG backend and pysimplegui Z : pop up window to select absorber redshift and linelist j : pop up window to select a corresponding rest frame transition and linelist K : pop up window to select multiple absorber lines and plot them 0 : pop up window to select identified absorber list to show with 1d spectrum + : pop up window to select filename of pre-identified list of individual absorbers and plot them q : Quit Program. --------------------------------------------------------------------------- Written By: Rongmon Bordoloi August 2020. HEALTH WARNING: The GUI implementation is still in alpha version and is quite unstable. User must be careful to make sure that they exit individual GUIs first by pressing the correct button before closing the plot window. --------------------------------------------------------------------------- import matplotlib matplotlib.use('TkAgg') from linetools.spectra.xspectrum1d import XSpectrum1D from GUIs import rb_plot_spec as r sp=XSpectrum1D.from_file('PG0832+251_nbin3_coadd.fits') r.rb_plot_spec(sp.wavelength.value,sp.flux.value,sp.sig.value) ''') # Making sure any drawn line list remains drawn self.DrawLineList(self.label) q = np.where(self.zabs_list['List'] != 'None') if len(q[0] > 0): self.draw_any_linelist() plt.draw() self.fig.canvas.draw()
# -*- coding: utf-8 -*- import matplotlib.pyplot as plt from astropy.io import fits from astropy.convolution import Gaussian2DKernel, MexicanHat2DKernel, convolve import os # Variables for the filename path = "/home/abeelen/Herschel/DDT_mustdo_5/PLCK_SZ_G004.5-19.6-1/" filename = "OD1271_0x50012da8L_SpirePhotoLargeScan_PLCK_SZ_G004.5-19.6-1_destriped_PMW.fits" # Load the data fits_data = fits.getdata(path+filename,"image") # Make the Mexican hat filter mex = MexicanHat2DKernel(2, x_size=5, y_size=5) z = convolve(fits_data, mex, boundary = 'None') # Make the gaussian filter #gauss = Gaussian2DKernel(stddev=2) #z = convolve(fits_data, gauss, boundary='extend') # Plot the figure pixels = None fig, main_axes = plt.subplots() #main_axes.imshow(fits_data, origin="lower", interpolation="None") main_axes.imshow(z, origin="lower", interpolation="None") plt.show() #header = fits_data #print header
def smooth_image_toresolution(fn, outfn, target_resolution, clobber=False, verbose=True, write=True): """ Smooth images with known beam size to a target beam size Parameters ---------- fn : str outfn : str target_resolution : `~astropy.units.quantity.Quantity` A degree-equivalent value that specifies the beam size in the output image verbose : bool Print messages at each step? clobber : bool Overwrite files if they exist? write : bool Write the file to the output filename? Returns ------- f : `~astropy.io.fits.PrimaryHDU` The smoothed FITS image with appropriately updated BMAJ/BMIN """ f = fits.open(fn) header = f[0].header native_beamsize = header['BMAJ']*u.deg if header['BMIN'] != header['BMAJ']: warnings.warn("Asymmetric beam not well-supported: " "the images should be smoothed to have symmetric beams " "prior to using this task") kernelsize = ((target_resolution*FWHM_TO_SIGMA)**2 - (native_beamsize*FWHM_TO_SIGMA)**2)**0.5 if kernelsize.value < 0: raise ValueError("Cannot smooth to target resolution: " "smaller than current resolution.") platescale = FITS_header_tools.header_to_platescale(f[0].header, use_units=True) kernelsize_pixels = (kernelsize/platescale).decompose() if not kernelsize_pixels.unit.is_equivalent(u.dimensionless_unscaled): raise ValueError("Kernel size not in valid units") kernel = convolution.Gaussian2DKernel(kernelsize_pixels.value) if verbose: print("Convolving with {0}-pixel kernel".format(kernelsize_pixels)) if kernelsize_pixels > 15: sm = convolution.convolve_fft(f[0].data, kernel, interpolate_nan=True) else: sm = convolution.convolve(f[0].data, kernel) f[0].data = sm comment = "Smoothed with {0:03f}\" kernel".format(kernelsize.to(u.arcsec).value) f[0].header['BMAJ'] = (target_resolution.to(u.deg).value, comment) f[0].header['BMIN'] = (target_resolution.to(u.deg).value, comment) if write: f.writeto(outfn, clobber=clobber) return f
def Smoo(self, smoo_scale): """ smooth the input power using a convolve function """ g = Gaussian1DKernel(stddev=smoo_scale) self.power = convolve(self.power, g, boundary='extend')
plt.matshow(z_mdt, cmap="RdBu", vmin=vmin, vmax=vmax) plt.title("Before") plt.matshow(z_gmdt, cmap="RdBu", vmin=vmin, vmax=vmax) plt.title("Before") print("extending MDT and GMDT ...") # NOTE: Gaussian widths/range optimized for 5 km grid widths = [3, 5, 7, 9, 11] z_mdt = extend_field(z_mdt, mask, gauss_widths=widths, taper=None) z_gmdt = extend_field(z_gmdt, mask, gauss_widths=widths, taper=None) # Smooth artefacts including GLs with zeros over land z_mdt[mask == 1] = 0.0 z_gmdt[mask == 1] = 0.0 z_mdt = convolve(z_mdt, Gaussian2DKernel(3), boundary="extend") z_gmdt = convolve(z_gmdt, Gaussian2DKernel(3), boundary="extend") z_mdt[mask == 1] = np.nan z_gmdt[mask == 1] = np.nan plt.matshow(z_mdt - np.nanmean(z_mdt), cmap="RdBu", vmin=-1.5, vmax=1.5) plt.title("After") plt.colorbar() plt.matshow(z_gmdt - np.nanmean(z_gmdt), cmap="RdBu", vmin=-1.5, vmax=1.5) plt.title("After") plt.colorbar() # --- Regrid all fields to Cube grid and save --- # # Regrid fields
def main(): """ The purpose of this code is to compare the Vs+V1+V1n map (this is currently the top middle panel in Fig 7) with the Vs+V2+V1n map. This is one of the plots the referee wanted to see. I think they think that this will display the rotation better. I'm not entirely sure. This code is completely based on the codes -- 1. stitche_vel_vdisp_cube.py and 2. contours_from_linefits.py. """ # Generate the Vs + V2 + V1n map #genmap() # Read in the new map and make contours map_vel_comp2_hdu = fits.open(gaussfits_dir + 'vel_cube_comp2.fits') map_vel_comp2_new_hdu = fits.open(gaussfits_dir + 'vel_cube_vs_v2_v1n.fits') map_vel_comp2 = map_vel_comp2_hdu[0].data map_vel_comp2_new = map_vel_comp2_new_hdu[0].data # Diagnostic figures # Do not delete this code block. Useful for checking. """ fig = plt.figure() ax1 = fig.add_subplot(121) ax2 = fig.add_subplot(122) ax1.imshow(map_vel_comp2, origin='lower', vmin=-350, vmax=350) ax2.imshow(map_vel_comp2_new, origin='lower', vmin=-350, vmax=350) plt.show() """ # ------- Contours --------- # # Plotting # Change MPL RC params first to stop using TeX for all text # becasue I can't use bold text with TeX. mpl.rcParams['text.usetex'] = False # Bold text f = FontProperties() f.set_weight('bold') # read in i band SDSS image sdss_i, wcs_sdss = vcm.get_sdss('i') # read in lzifu output file lzifu_hdulist, wcs_lzifu = vcm.get_lzifu_products() # plot sdss image fig, ax = vcm.plot_sdss_image(sdss_i, wcs_sdss) # draw contours x = np.arange(58) y = np.arange(58) X, Y = np.meshgrid(x,y) # get colormap colorbrewer_cm = vcm.get_colorbrewer_cm('blue2yellow') # select contour map to plot and set the variables # set the variables, levels, and limits below con_map = map_vel_comp2_new # apply min and max limits minlim = -500 maxlim = 500 minidx = np.where(con_map < minlim) maxidx = np.where(con_map > maxlim) con_map[minidx] = np.nan con_map[maxidx] = np.nan levels = np.array([-350, -250, -200, -150, -100, 0, 100, 150, 200, 250, 350]) # vel both comp # try smoothing the map to get smoother contours # define kernel kernel = Gaussian2DKernel(stddev=0.9) con_map = convolve(con_map, kernel, boundary='extend') c = ax.contour(X, Y, con_map, transform=ax.get_transform(wcs_lzifu),\ levels=levels, cmap=colorbrewer_cm, linewidths=2.0, interpolation='None') # add colorbar inside figure cbaxes = inset_axes(ax, width='30%', height='3%', loc=8, bbox_to_anchor=[0.02, 0.08, 1, 1], bbox_transform=ax.transAxes) cb = plt.colorbar(c, cax=cbaxes, ticks=[min(levels), max(levels)], orientation='horizontal') cb.ax.get_children()[0].set_linewidths(16.0) cb.ax.set_xlabel(r'$\mathrm{Radial\ Velocity\ [km\, s^{-1}]}$', fontsize=15) plt.show() return None
def main(): # ----------------------- Preliminary stuff ----------------------- # ext_root = "romansim_prism_" img_basename = '5deg_' img_filt = 'Y106_' exptime1 = '_900s' exptime2 = '_1800s' exptime3 = '_3600s' all_exptimes = [exptime1, exptime2, exptime3] # ----------------------- Using emcee ----------------------- # # Labels for corner and trace plots label_list_sn = [r'$z$', r'$Day$', r'$A_V [mag]$'] # Set jump sizes # ONLY FOR INITIAL POSITION SETUP jump_size_z = 0.1 jump_size_av = 0.5 # magnitudes jump_size_day = 3 # days # Setup dims and walkers nwalkers = 500 niter = 1000 ndim_sn = 3 # ----------------------- Loop over all simulated and extracted SN spectra ----------------------- # # Arrays to loop over pointings = np.arange(1, 30) detectors = np.arange(1, 19, 1) for pt in pointings: for det in detectors: img_suffix = img_filt + str(pt) + '_' + str(det) # --------------- Read in sed.lst sedlst_header = ['segid', 'sed_path'] sedlst_path = roman_slitless_dir + '/pylinear_lst_files/' + 'sed_' + img_suffix + '.lst' sedlst = np.genfromtxt(sedlst_path, dtype=None, names=sedlst_header, encoding='ascii') print("Read in sed.lst from:", sedlst_path) print("Number of spectra in file:", len(sedlst)) # --------------- Read in the extracted spectra # For all exposure times ext_spec_filename1 = ext_spectra_dir + ext_root + img_suffix + exptime1 + '_x1d.fits' ext_hdu1 = fits.open(ext_spec_filename1) print("Read in extracted spectra from:", ext_spec_filename1) ext_spec_filename2 = ext_spectra_dir + ext_root + img_suffix + exptime2 + '_x1d.fits' ext_hdu2 = fits.open(ext_spec_filename2) print("Read in extracted spectra from:", ext_spec_filename2) ext_spec_filename3 = ext_spectra_dir + ext_root + img_suffix + exptime3 + '_x1d.fits' ext_hdu3 = fits.open(ext_spec_filename3) print("Read in extracted spectra from:", ext_spec_filename3) print('\n') all_hdus = [ext_hdu1, ext_hdu2, ext_hdu3] # --------------- loop and find all SN segids all_sn_segids = [] for i in range(len(sedlst)): if 'salt' in sedlst['sed_path'][i]: all_sn_segids.append(sedlst['segid'][i]) print('ALL SN segids in this file:', all_sn_segids) # --------------- Loop over all extracted files and SN in each file expcount = 0 for ext_hdu in all_hdus: for segid in all_sn_segids: #if segid == 188 and img_suffix == 'Y106_0_17': # print('Skipping SN', segid, 'in img_suffix', img_suffix) # continue print("\nFitting SegID:", segid, "with exposure time:", all_exptimes[expcount]) # ----- Get spectrum segid_idx = int(np.where(sedlst['segid'] == segid)[0]) template_name = os.path.basename( sedlst['sed_path'][segid_idx]) template_inputs = get_template_inputs( template_name) # needed for plotting wav = ext_hdu[('SOURCE', segid)].data['wavelength'] flam = ext_hdu[('SOURCE', segid )].data['flam'] * pylinear_flam_scale_fac ferr_lo = ext_hdu[ ('SOURCE', segid)].data['flounc'] * pylinear_flam_scale_fac ferr_hi = ext_hdu[ ('SOURCE', segid)].data['fhiunc'] * pylinear_flam_scale_fac # Smooth with boxcar smoothing_width_pix = 5 sf = convolve(flam, Box1DKernel(smoothing_width_pix)) # ----- Check SNR snr = get_snr(wav, flam) print("SNR for this spectrum:", "{:.2f}".format(snr), get_snr(wav, sf)) if snr < 3.0: print("Skipping due to low SNR.") continue # ----- Set noise level based on snr #noise_lvl = 1/snr # Create ferr array #ferr = noise_lvl * flam ferr = (ferr_lo + ferr_hi) / 2.0 # ----- Get optimal starting position z_prior, phase_prior, av_prior = get_optimal_position( wav, flam, ferr) rsn_init = np.array([z_prior, phase_prior, av_prior]) # redshift, day relative to peak, and dust extinction # generating ball of walkers about optimal position defined above pos_sn = np.zeros(shape=(nwalkers, ndim_sn)) for i in range(nwalkers): # ---------- For SN rsn0 = float(rsn_init[0] + jump_size_z * np.random.normal(size=1)) rsn1 = int(rsn_init[1] + jump_size_day * np.random.normal(size=1)) rsn2 = float(rsn_init[2] + jump_size_av * np.random.normal(size=1)) rsn = np.array([rsn0, rsn1, rsn2]) pos_sn[i] = rsn # ----- Clip data at the ends wav_idx = np.where((wav > 7600) & (wav < 18000))[0] sn_wav = wav[wav_idx] sn_flam = flam[wav_idx] sn_ferr = ferr[wav_idx] # ----- Set up args args_sn = [sn_wav, sn_flam, sn_ferr] print("logpost at starting position for SN:") print(logpost_sn(rsn_init, sn_wav, sn_flam, sn_ferr)) print("Starting position:", rsn_init) # ----- Now run emcee on SN snstr = str( segid) + '_' + img_suffix + all_exptimes[expcount] emcee_savefile = results_dir + \ 'emcee_sampler_sn' + snstr + '.h5' if not os.path.isfile(emcee_savefile): backend = emcee.backends.HDFBackend(emcee_savefile) backend.reset(nwalkers, ndim_sn) with Pool(4) as pool: sampler = emcee.EnsembleSampler(nwalkers, ndim_sn, logpost_sn, args=args_sn, pool=pool, backend=backend) sampler.run_mcmc(pos_sn, niter, progress=True) print(f"{bcolors.GREEN}") print("Finished running emcee.") print("Mean acceptance Fraction:", np.mean(sampler.acceptance_fraction), "\n") print(f"{bcolors.ENDC}") # ---------- Stuff needed for plotting truth_dict = {} truth_dict['z'] = template_inputs[0] truth_dict['phase'] = template_inputs[1] truth_dict['Av'] = template_inputs[2] read_pickle_make_plots_sn('sn' + snstr, ndim_sn, args_sn, label_list_sn, truth_dict, results_dir) print("Finished plotting results.") expcount += 1 # --------------- close all open fits files ext_hdu1.close() ext_hdu2.close() ext_hdu3.close() return None
def find_lyman_break(SpectralDataObject): #smooth the data first because its noisy gauss_kernel = Gaussian1DKernel(5) smoothed_data = convolve(SpectralDataObject, gauss_kernel)
def plot(): redshift = 1 with open('/home/lc585/qsosed/input.yml', 'r') as f: parfile = yaml.load(f) # Load stuff fittingobj = load(parfile) lin = fittingobj.get_lin() qsomag = fittingobj.get_qsomag() whmin = fittingobj.get_whmin() whmax = fittingobj.get_whmax() ignmin = fittingobj.get_ignmin() ignmax = fittingobj.get_ignmax() galcnt = fittingobj.get_galcnt() galspc = fittingobj.get_galspc() wavlen = fittingobj.get_wavlen() fig, ax = plt.subplots(figsize=figsize(1, vscale=0.9)) # ax.plot(wavlen,wavlen*fluxtmp,color='black') # import lineid_plot # line_wave = [1216, # 1549, # 1909, # 2798, # 4861, # 6563, # 18744] # line_names = [r'Ly$\alpha$', # r'C\,{\sc iv}', # r'C\,{\sc iii}]', # r'Mg\,{\sc ii}', # r'H$\beta$', # r'H$\alpha$', # r'Pa$\alpha$'] # lineid_plot.plot_line_ids(wavlen, wavlen*fluxtmp, line_wave, line_names, ax=ax, arrow_tip=10000) plslp1 = -0.478 plslp2 = -0.199 plbrk = 2402 bbt = 1306 bbflxnrm = 3.673 elscal = 1.240 scahal = 0.713 galfra = 0.4 bcnrm = 0.135 ebv = 0.0 flux = np.zeros(len(wavlen), dtype=np.float) flxnrm = parfile['quasar']['flxnrm'] wavnrm = parfile['quasar']['wavnrm'] # Define normalisation constant to ensure continuity at wavbrk const2 = flxnrm / (wavnrm**(-plslp2)) const1 = const2 * ((plbrk**(-plslp2)) / (plbrk**(-plslp1))) wavnumbrk = wav2num(wavlen, plbrk) flux[:wavnumbrk] = flux[:wavnumbrk] + pl(wavlen[:wavnumbrk], plslp1, const1) flux[wavnumbrk:] = flux[wavnumbrk:] + pl(wavlen[wavnumbrk:], plslp2, const2) # Now add steeper power-law component for sub-Lyman-alpha wavelengths # Define normalisation constant to ensure continuity at wavbrk plbrk_tmp = parfile['quasar']['pl_steep']['brk'] plslp_tmp = plslp1 + parfile['quasar']['pl_steep']['step'] plbrknum_tmp = wav2num(wavlen, plbrk_tmp) const_tmp = flux[plbrknum_tmp] / (plbrk_tmp**-plslp_tmp) flux[:plbrknum_tmp] = pl(wavlen[:plbrknum_tmp], plslp_tmp, const_tmp) flux_pl = flux * 1.0 # Hot blackbody --------------------------------------------------- bbwavnrm = parfile['quasar']['bb']['wavnrm'] flux = flux + bb( wavlen * u.AA, bbt * u.K, bbflxnrm, bbwavnrm * u.AA, units='freq') flux_bb = bb(wavlen * u.AA, bbt * u.K, bbflxnrm, bbwavnrm * u.AA, units='freq') # Balmer continuum -------------------------------------------------- # Add Balmer Continuum and blur to simulate effect of bulk-velocity # shifts comparable to those present in emission lines # Determine height of power-law continuum at wavelength wbcnrm to allow # correct scaling of Balmer continuum contribution wbcnrm = parfile['quasar']['balmercont']['wbcnrm'] wbedge = parfile['quasar']['balmercont']['wbedge'] tbc = parfile['quasar']['balmercont']['tbc'] taube = parfile['quasar']['balmercont']['taube'] vfwhm = parfile['quasar']['balmercont']['vfwhm'] # mean wavelength increment winc = np.diff(wavlen).mean() cfact = flux[wav2num(wavlen, wbcnrm)] flux = flux / cfact flux_bc = bc(wavlen=wavlen * u.AA, tbb=tbc * u.K, fnorm=bcnrm, taube=taube, wavbe=wbedge * u.AA, wnorm=wbcnrm * u.AA) vsigma = vfwhm * (u.km / u.s) / 2.35 wsigma = wbedge * u.AA * vsigma / const.c wsigma = wsigma.to(u.AA) psigma = wsigma / (winc * u.AA) # Performs a simple Gaussian smooth with dispersion psigma pixels gauss = Gaussian1DKernel(stddev=psigma) flux_bc = convolve(flux_bc, gauss) flux = flux + flux_bc #----------------------------------------------------------------- # Now convert to flux per unit wavelength # Presumably the emission line spectrum and galaxy spectrum # are already in flux per unit wavelength. # c / lambda^2 conversion flux = flux * (u.erg / u.s / u.cm**2 / u.Hz) flux = flux.to(u.erg / u.s / u.cm**2 / u.AA, equivalencies=u.spectral_density(wavlen * u.AA)) scale = flux[wav2num(wavlen, wavnrm)] flux = flxnrm * flux / scale flux_pl = flux_pl * (u.erg / u.s / u.cm**2 / u.Hz) flux_pl = flux_pl.to(u.erg / u.s / u.cm**2 / u.AA, equivalencies=u.spectral_density(wavlen * u.AA)) flux_pl = flxnrm * flux_pl / scale flux_bb = flux_bb * (u.erg / u.s / u.cm**2 / u.Hz) flux_bb = flux_bb.to(u.erg / u.s / u.cm**2 / u.AA, equivalencies=u.spectral_density(wavlen * u.AA)) flux_bb = flxnrm * flux_bb / scale flux_bc = flux_bc * (u.erg / u.s / u.cm**2 / u.Hz) flux_bc = flux_bc.to(u.erg / u.s / u.cm**2 / u.AA, equivalencies=u.spectral_density(wavlen * u.AA)) flux_bc = flxnrm * flux_bc / scale # Emission lines ------------------------------------------------- linwav, linval, conval = lin[:, 0], lin[:, 1], lin[:, 2] # Normalise such that continuum flux at wavnrm equal to that # of the reference continuum at wavnrm inorm = wav2num(wavlen, wavnrm) scale = flux[inorm] flux = conval[inorm] * flux / scale flux_pl = conval[inorm] * flux_pl / scale flux_bb = conval[inorm] * flux_bb / scale flux_bc = conval[inorm] * flux_bc / scale # Calculate Baldwin Effect Scaling for Halpha zbenrm = parfile['quasar']['el']['zbenrm'] beslp = parfile['quasar']['el']['beslp'] # Line added to stop enormous BE evolution at low z zval = np.max([redshift, zbenrm]) # I think this is the absolute magnitude of the SDSS sample as # a function of redshift, which is not the same as how the # absolute magnitude of a object of a given flux changes # as a function of redshift qsomag_itp = interp1d(qsomag[:, 0], qsomag[:, 1]) # Absolute magnitude at redshift z minus # normalisation absolute magnitude vallum = qsomag_itp(zval) - qsomag_itp(zbenrm) # Convert to luminosity vallum = 10.0**(-0.4 * vallum) scabe = vallum**(-beslp) flux_el = np.zeros_like(flux) flux_el[:whmin] = linval[:whmin] * np.abs( elscal) * flux[:whmin] / conval[:whmin] flux_el[whmax:] = linval[whmax:] * np.abs( elscal) * flux[whmax:] / conval[whmax:] flux[:whmin] = flux[:whmin] + linval[:whmin] * np.abs( elscal) * flux[:whmin] / conval[:whmin] flux[whmax:] = flux[whmax:] + linval[whmax:] * np.abs( elscal) * flux[whmax:] / conval[whmax:] # Scaling for Ha with Baldwin effect scatmp = elscal * scahal / scabe flux_el[whmin:whmax] = linval[whmin:whmax] * np.abs( scatmp) * flux[whmin:whmax] / conval[whmin:whmax] flux[whmin:whmax] = flux[whmin:whmax] + \ linval[whmin:whmax] * np.abs(scatmp) * flux[whmin:whmax] / conval[whmin:whmax] gznorm = parfile['gal']['znrm'] gplind = parfile['gal']['plind'] # Determine fraction of galaxy sed to add to unreddened quasar SED qsocnt = np.sum(flux[ignmin:ignmax]) # Factor cscale just to bring input galaxy and quasar flux zero-points equal cscale = qsocnt / galcnt # Find absolute magnitude of quasar at redshift z vallum = qsomag_itp(redshift) # Find absolute magnitude of quasar at redshift gznorm galnrm = qsomag_itp(gznorm) # Subtract supplied normalisation absolute magnitude vallum = vallum - galnrm # Convert to a luminosity vallum = 10.0**(-0.4 * vallum) # Luminosity scaling scaval = vallum**(gplind - 1.0) scagal = (galfra / (1.0 - galfra)) * scaval flux_gal = cscale * scagal * galspc # flux = flux + cscale * scagal * galspc ax.plot(wavlen[:wavnumbrk], wavlen[:wavnumbrk] * flux_pl[:wavnumbrk], color=cs[1], label='Accretion Disc') # ax.fill_between(wavlen[:wavnumbrk], wavlen[:wavnumbrk]*flux_pl[:wavnumbrk], facecolor=cs[1], alpha=0.2) ax.plot(wavlen[wavnumbrk:], wavlen[wavnumbrk:] * flux_pl[wavnumbrk:], color=cs[0], label='Accretion Disc') # ax.fill_between(wavlen[wavnumbrk:], wavlen[wavnumbrk:]*flux_pl[wavnumbrk:], facecolor=cs[0], alpha=0.2) ax.plot(wavlen, wavlen * (flux_bc), color=cs[2], label='Balmer Continuum') # ax.fill_between(wavlen, wavlen*(flux_bc), facecolor=cs[2], alpha=0.2) ax.plot(wavlen, wavlen * (flux_bb), color=cs[4], label='Hot Dust') # ax.fill_between(wavlen, wavlen*(flux_bb), facecolor=cs[4], alpha=0.2) # ax.plot(wavlen, wavlen*(flux_gal), color=cs[3], label='Galaxy') # ax.fill_between(wavlen, wavlen*(flux_gal), facecolor=cs[3], alpha=0.2) ax.plot(wavlen, wavlen * flux, color='black', label='Total') ax.legend() ax.set_xlim(1216, 20000) ax.set_ylim(0, 10000) ax.set_ylabel(r'${\lambda}F_{\lambda}$ [Arbitary Units]') ax.set_xlabel(r'Wavelength $\lambda$ [${\rm \AA}$]') plt.tight_layout() plt.subplots_adjust(top=0.85) fig.savefig('/home/lc585/thesis/figures/chapter05/sed_model.pdf') plt.show() return None
def smooth(x, window_len=9, window='hanning'): """ Smooth the data using a window with requested size. This method is based on the convolution of a scaled window with the signal. The signal is prepared by introducing reflected copies of the signal (with the window size) in both ends so that transient parts are minimized in the begining and end part of the output signal. Parameters ---------- x : array_like the input signal window_len : int The length of the smoothing window window : str The type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman' 'flat' window will produce a moving average smoothing. Returns ------- out : The smoothed signal Example ------- >>> t=linspace(-2,2,0.1) >>> x=sin(t)+randn(len(t))*0.1 >>> y=smooth(x) See Also -------- numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve scipy.signal.lfilter TODO: the window parameter could be the window itself if an array instead of a string """ if isinstance(x, list): x = np.array(x) if x.ndim != 1: raise ValueError("smooth only accepts 1 dimension arrays.") if len(x) < window_len: print("length of x: ", len(x)) print("window_len: ", window_len) raise ValueError("Input vector needs to be bigger than window size.") if window_len < 3: return x if (window_len % 2) == 0: window_len = window_len + 1 if window not in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']: raise ValueError("Window is on of 'flat', 'hanning', \ 'hamming', 'bartlett', 'blackman'") if window == 'flat': # moving average w = np.ones(window_len, 'd') else: w = eval('np.' + window + '(window_len)') y = convolve(x, w / w.sum(), normalize_kernel=False, boundary='extend') # return the smoothed signal return y
def convolution_smooth(spectrum, kernel): """ Apply a convolution based smoothing to the spectrum. The kernel must be one of the 1D kernels defined in `astropy.convolution`. This method can be used along but also is used by other specific methods below. If the spectrum uncertainty exists and is StdDevUncertainty, VarianceUncertainty or InverseVariance then the errors will be propagated through the convolution using a standard propagation of errors. The covariance is not considered, currently. Parameters ---------- spectrum : `~specutils.Spectrum1D` The `~specutils.Spectrum1D` object to which the smoothing will be applied. kernel : `astropy.convolution.Kernel1D` subclass or array. The convolution based smoothing kernel - anything that `astropy.convolution.convolve` accepts. 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 ``spectrum`` and ``kernel`` are not the correct types. """ # Parameter checks if not isinstance(spectrum, Spectrum1D): raise ValueError('The spectrum parameter must be a Spectrum1D object') # Get the flux of the input spectrum flux = spectrum.flux # Smooth based on the input kernel smoothed_flux = convolution.convolve(flux, kernel) # Propagate the uncertainty if it exists... uncertainty = copy.deepcopy(spectrum.uncertainty) if uncertainty is not None: if isinstance(uncertainty, StdDevUncertainty): # Convert values = uncertainty.array ivar_values = 1 / values**2 # Propagate prop_ivar_values = convolution.convolve(ivar_values, kernel) # Put back in uncertainty.array = 1 / np.sqrt(prop_ivar_values) elif isinstance(uncertainty, VarianceUncertainty): # Convert values = uncertainty.array ivar_values = 1 / values # Propagate prop_ivar_values = convolution.convolve(ivar_values, kernel) # Put back in uncertainty.array = 1 / prop_ivar_values elif isinstance(uncertainty, InverseVariance): # Convert ivar_values = uncertainty.array # Propagate prop_ivar_values = convolution.convolve(ivar_values, kernel) # Put back in uncertainty.array = prop_ivar_values else: uncertainty = None warnings.warn("Uncertainty is {} but convolutional error propagation is not defined for that type. Uncertainty will be dropped in the convolved spectrum.".format(type(uncertainty)), AstropyUserWarning) # Return a new object with the smoothed flux. return Spectrum1D(flux=u.Quantity(smoothed_flux, spectrum.unit), spectral_axis=u.Quantity(spectrum.spectral_axis, spectrum.spectral_axis_unit), wcs=spectrum.wcs, uncertainty=uncertainty, velocity_convention=spectrum.velocity_convention, rest_value=spectrum.rest_value)
def frame_filter_lowpass(array, mode='gauss', median_size=5, fwhm_size=5, gauss_mode='conv', kernel_sz=None, psf=None, mask=None, iterate=True, **kwargs): """ Low-pass filtering of input frame depending on parameter ``mode``. Parameters ---------- array : numpy ndarray Input array, 2d frame. mode : {'median', 'gauss', 'moff', 'psf'}, str optional Type of low-pass filtering. median_size : int, optional Size of the median box for filtering the low-pass median filter. fwhm_size : float, optional Size of the Gaussian kernel for the low-pass Gaussian filter. gauss_mode : {'conv', 'convfft'}, str optional 'conv' uses the multidimensional gaussian filter from scipy.ndimage and 'convfft' uses the fft convolution with a 2d Gaussian kernel. kernel_sz: int or None, optional Size of the kernel in pixels for 2D Gaussian and Moffat convolutions. If None, astropy.convolution will automatically consider 8*radius kernel sizes. psf: numpy ndarray, optional Input normalised and centered psf, 2d frame. Should be provided if mode is set to 'psf'. mask: numpy ndarray, optional Binary mask indicating where the low-pass filtered image should be interpolated with astropy.convolution. This option can be useful if the low-pass filtered image is aimed to capture low-spatial frequency sky signal, while avoiding a stellar halo (set to one in the binary mask). Note: only works with Gaussian kernel or PSF convolution. iterate: bool, opt If the first convolution leaves nans, whether to continue replacing nans by interpolation until they are all replaced. **kwargs : dict Passed through to the astropy.convolution.convolve or convolve_fft function. Returns ------- filtered : numpy ndarray Low-pass filtered image. """ if array.ndim != 2: raise TypeError('Input array is not a frame or 2d array.') if not isinstance(median_size, int): raise ValueError('`Median_size` must be integer') if mask is not None: if mode== 'median': msg="Masking not available for median filter" if mask.shape != array.shape: msg = "Mask dimensions should be the same as array" raise TypeError(msg) if mode == 'median': # creating the low_pass filtered (median) image filtered = median_filter(array, median_size, mode='nearest') elif mode == 'gauss': # 2d Gaussian filter sigma = fwhm_size * gaussian_fwhm_to_sigma if gauss_mode == 'conv': filtered = convolve(array, Gaussian2DKernel(x_stddev=sigma, x_size=kernel_sz, y_size=kernel_sz), mask=mask, **kwargs) if iterate and np.sum(np.isnan(filtered))>0: filtered = interp_nan(filtered, Gaussian2DKernel(x_stddev=sigma, x_size=kernel_sz, y_size=kernel_sz), convolve=convolve) elif gauss_mode == 'convfft': # FFT Convolution with a 2d gaussian kernel created with Astropy. filtered = convolve_fft(array, Gaussian2DKernel(x_stddev=sigma, x_size=kernel_sz, y_size=kernel_sz), mask=mask, **kwargs) if iterate and np.sum(np.isnan(filtered))>0: filtered = interp_nan(filtered, Gaussian2DKernel(x_stddev=sigma, x_size=kernel_sz, y_size=kernel_sz), convolve=convolve_fft, **kwargs) else: raise TypeError('2d Gaussian filter mode not recognized') elif mode == 'psf': if psf is None: raise TypeError('psf should be provided for convolution') elif psf.ndim != 2: raise TypeError('Input psf is not a frame or 2d array.') if psf.shape[-1] > array.shape[-1]: raise TypeError('Input psf is larger than input array. Crop.') # psf convolution filtered = convolve_fft(array, psf, mask=mask, **kwargs) if iterate and np.sum(np.isnan(filtered))>0: filtered = interp_nan(filtered, psf, convolve=convolve_fft, **kwargs) else: raise TypeError('Low-pass filter mode not recognized') return filtered
def do_plot(self): if self.plate != int(self.e1.get()) or self.mjd != int(self.e2.get()): self.plate = int(self.e1.get()) self.mjd = int(self.e2.get()) self.fiber = int(self.e3.get()) self.znum = int(self.e5.get()) self.platepath = join(environ['BOSS_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, 'spPlate-%s-%s.fits' % (self.plate, self.mjd)) hdu = fits.open(self.platepath) self.specs = hdu[0].data self.wave = 10**(hdu[0].header['COEFF0'] + n.arange(hdu[0].header['NAXIS1']) * hdu[0].header['COEFF1']) self.models = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[2].data self.fiberid = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.FIBERID self.type1 = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.CLASS1 self.type2 = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.CLASS2 self.type3 = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.CLASS3 self.type4 = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.CLASS4 self.type5 = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.CLASS5 self.z = n.zeros((self.fiberid.shape[0],5)) self.z[:,0] = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.Z1 self.z[:,1] = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.Z2 self.z[:,2] = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.Z3 self.z[:,3] = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.Z4 self.z[:,4] = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.Z5 self.zwarning = fits.open(join(environ['REDMONSTER_SPECTRO_REDUX'], environ['RUN2D'], '%s' % self.plate, environ['RUN1D'], 'redmonster-%s-%s.fits' % (self.plate, self.mjd)))[1].data.ZWARNING else: self.fiber = int(self.e3.get()) f = Figure(figsize=(10,6), dpi=100) a = f.add_subplot(111) loc = n.where(self.fiberid == self.fiber)[0] if self.znum == 1: z = self.z[loc[0],0] thistype = self.type1[loc[0]] elif self.znum == 2: z = self.z[loc[0],1] thistype = self.type2[loc[0]] elif self.znum == 3: z = self.z[loc[0],2] thistype = self.type3[loc[0]] elif self.znum == 4: z = self.z[loc[0],3] thistype = self.type4[loc[0]] elif self.znum == 5: z = self.z[loc[0],4] thistype = self.type5[loc[0]] if self.var.get() == 0: if self.restframe.get() == 0: a.plot(self.wave, self.specs[self.fiber], color='black') elif self.restframe.get() == 1: a.plot(self.wave/(1+self.z[loc][0]), self.specs[self.fiber], color='black') elif self.var.get() == 1: smooth = self.e4.get() if smooth is '': if self.restframe.get() == 0: a.plot(self.wave, self.specs[self.fiber], color='black') elif self.restframe.get() == 1: a.plot(self.wave/(1+z), self.specs[self.fiber], color='black') else: if self.restframe.get() == 0: a.plot(self.wave, convolve(self.specs[self.fiber], Box1DKernel(int(smooth))), color='black') elif self.restframe.get() == 1: a.plot(self.wave/(1+z), convolve(self.specs[self.fiber], Box1DKernel(int(smooth))), color='black') # Overplot model if len(loc) is not 0: if self.restframe.get() == 0: #a.plot(self.wave, self.models[loc[0]], color='black') # This for when multiple models are in redmonster file a.plot(self.wave, self.models[loc[0],self.znum-1], color='cyan') if self.ablines.get() == 1: for i, line in enumerate(self.ablinelist): if ((line*(1+z) > self.wave[0]) & (line*(1+z) < self.wave[-1])): a.axvline(line*(1+z), color='blue', linestyle='--', label=self.ablinenames[i]) if self.emlines.get() == 1: for i, line in enumerate(self.emlinelist): if (line*(1+z) > self.wave[0]) & (line*(1+z) < \ self.wave[-1]): a.axvline(line*(1+z), color='red', linestyle='--', label=self.emlinenames[i]) if self.ablines.get() == 1 or self.emlines.get() == 1: a.legend(prop={'size':10}) elif self.restframe.get() == 1: a.plot(self.wave/(1+z), self.models[loc[0],self.znum-1], color='cyan') if self.ablines.get() == 1: for i, line in enumerate(self.ablinelist): if (line > self.wave[0]) & (line < self.wave[-1]): a.axvline(line, color='blue', linestyle='--', label=self.ablinenames[i]) if self.emlines.get() == 1: for i, line in enumerate(self.emlinelist): if (line > self.wave[0]) & (line < self.wave[-1]): a.axvline(line, color='red', linestyle='--', label=self.emlinenames[i]) if self.ablines.get() == 1 or self.emlines.get() == 1: a.legend(prop={'size':10}) a.set_title('Plate %s Fiber %s: z=%s class=%s zwarning=%s' % (self.plate, self.fiber, z, thistype, self.zwarning[loc[0]])) else: print('Fiber %s is not in redmonster-%s-%s.fits' % \ (self.fiber, self.plate, self.mjd)) a.set_title('Plate %s Fiber %s' % (self.plate, self.fiber)) if self.restframe.get() == 1: lower_data, upper_data = self.set_limits() a.axis([self.wave[0]/(1+z)-100,self.wave[-1]/(1+z)+100, lower_data,upper_data]) elif self.restframe.get() == 0: lower_data, upper_data = self.set_limits() a.axis([self.wave[0]-100,self.wave[-1]+100,lower_data,upper_data]) a.set_xlabel('Wavelength ($\AA$)') a.set_ylabel('Flux ($10^{-17} erg\ cm^2 s^{-1} \AA^{-1}$)') canvas = FigureCanvasTkAgg(f, master=self.root) canvas.get_tk_widget().grid(row=0, column=5, rowspan=20) toolbar_frame = Frame(self.root) toolbar_frame.grid(row=20,column=5) toolbar = NavigationToolbar2TkAgg( canvas, toolbar_frame ) canvas.show()
def w80eval(wl: np.ndarray, spec: np.ndarray, wl0: float, smooth: float = None, clip_negative_flux: bool = True) -> tuple: """ Evaluates the W80 parameter of a given emission fature. Parameters ---------- wl : array-like Wavelength vector. spec : array-like Flux vector. wl0 : number Central wavelength of the emission feature. smooth : float Smoothing sigma to apply after the cumulative sum. clip_negative_flux : bool Sets negative flux values to zero. Returns ------- w80 : float The resulting w80 parameter. r0 : float r1 : float velocity : numpy.ndarray Velocity vector. velocity_spectrum : numpy.ndarray Spectrum in velocity coordinates. Notes ----- W80 is the width in velocity space which encompasses 80% of the light emitted in a given spectral feature. It is widely used as a proxy for identifying outflows of ionized gas in active galaxies. For instance, see Zakamska+2014 MNRAS. """ velocity = (wl * units.angstrom).to( units.km / units.s, equivalencies=units.doppler_relativistic(wl0 * units.angstrom)) if not (spec == 0.0).all() and not np.isnan(spec).all(): y = ma.masked_invalid(spec) if clip_negative_flux: y = np.clip(y, a_min=0.0, a_max=None) if smooth is not None: kernel = Gaussian1DKernel(smooth) y_mask = copy.deepcopy(y.mask) y = ma.array(data=convolve(y, kernel=kernel, boundary='extend'), mask=y_mask) cumulative = cumtrapz(y[~y.mask], velocity[~y.mask], initial=0)[0] if len(cumulative.shape) > 1: raise ValueError( f'cumulative must have only one dimension, but it has {len(cumulative.shape)}.' ) cumulative /= cumulative.max() r0 = velocity[(np.abs(cumulative - 0.1)).argsort()[0]].value r1 = velocity[(np.abs(cumulative - 0.9)).argsort()[0]].value w80 = r1 - r0 else: w80, r0, r1 = np.nan, np.nan, np.nan return w80, r0, r1, velocity, spec
c=colors[k], source=True) except: print( "\n\nLSST (Chang) p(z) not available. Plotting whitebook p(z) estimate for %.4lf.\n\n" % ilims[ilim]) pl.plot(zs, whitebook_pz(zs, ilims[ilim]), label=ilim, lw=1.5, c=colors[k]) elg_pz = elg_pz(interp=True) smooth_elgs = convolve(elg_pz(zs), Box1DKernel(30)) ## Hildebrandt et al. (2009) -- measured dndz. midz, pz_H09 = getpz_H09() pz_H09 = interp1d(midz, pz_H09, kind='linear', bounds_error=False, fill_value=0.0) ## BX: 'khaki' colors = [ 'purple', 'lightskyblue', 'mediumseagreen', 'khaki', 'dodgerblue', 'darkgreen', 'r' ] labels = [
def highpassflist(signal, highpassWidth): g = Box1DKernel(highpassWidth) return convolve(signal, g, boundary='extend')
def spectrometer_convolve(self, spec): """ This method convolves a spectrum with a wavelength-dependent spectral resolving power R=lambda/delta lambda, where delta lambda is the FWHM of an unresolved line at a wavelength lambda. This is accomplished by internally changing the sampling of the spectrum, such that delta-lambda is sampled by exactly a constant number of samples as a function of wavelength. The convolution is then accomplished using the convolution theorem and knowledge that the kernel is independent of wavelength. Parameters ---------- spec: pandeia.engine.astro_spectrum.AstroSpectrum instance The input spectrum to convolve Returns ------- spec: pandeia.engine.astro_spectrum.AstroSpectrum instance Same dimensions as input spec, but now convolved according to the wavelength-dependent resolving power of the instrument, if applicable. Same as the input spec in the case of no dispersion (i.e. imaging). """ r = self.get_resolving_power(spec.wave) if r is None: # no dispersion defined so return unmolested spectrum return spec dw_min = np.min(np.abs(spec.wave - np.roll(spec.wave, 1))) # find the minimum spacing between wavelengths fwhm = spec.wave / r # FWHM of resolution element as a function of wavelength fwhm_s = np.min(fwhm / dw_min) # find min of FWHM expressed in units of minimum spacing (i.e. sampling) # but do not allow the sampling FWHM to be less than Nyquist fwhm_s = np.max([2., fwhm_s]) # divide FWHM(wave) by the FWHM of the sampling to get sampling as a function of wavelength ds = fwhm / fwhm_s # use the min as a starting point; initialize array w = np.min(spec.wave) # it's much faster (~50%) to append to lists than np.array()'s wave_constfwhm = [] # doing this as a loop is slow, but straightforward. while w < np.max(spec.wave): # use interpolation to get delta-wavelength from the sampling as a function of wavelength. # this method is over 5x faster than the original use of scipy.interpolate.interp1d. w += np.interp(w, spec.wave, ds) wave_constfwhm.append(w) wave_constfwhm.pop() # remove last point which is an extrapolation wave_constfwhm = np.array(wave_constfwhm) # interpolate the flux onto the new wavelength set flux_constfwhm = spectrum_resample(spec.flux, spec.wave, wave_constfwhm) # convolve the flux with a gaussian kernel; first convert the FWHM to sigma sigma_s = fwhm_s / 2.3548 try: # for astropy < 0.4 g = Gaussian1DKernel(width=sigma_s) except TypeError: # for astropy >= 0.4 g = Gaussian1DKernel(sigma_s) # use boundary='extend' to set values outside the array to nearest array value. # this is the best approximation in this case. flux_conv = convolve(flux_constfwhm, g, normalize_kernel=True, boundary='extend') flux_oldsampling = np.interp(spec.wave, wave_constfwhm, flux_conv) spec.flux = flux_oldsampling return spec
print('\n*****************************************************') print('Objeto: ', filename) print('RA: ', ra) print('DEC: ', dec) print('----------------------------------------------------') ### SPLUS ### # Normalization max_splus = hdu_splus[0].data.max() norm_splus = hdu_splus[0].data / max_splus # Gaussian gauss_kernel = Gaussian2DKernel(1) result1 = convolve(hdu_splus[0].data, gauss_kernel) max_splus = result1.max() result1 = result1 / max_splus ### SDSS ### # Normalization max_norm = hdu_sdss[0].data.max() norm_sdss = hdu_sdss[0].data / max_norm # Gaussian gauss_kernel = Gaussian2DKernel(1) result2 = convolve(hdu_sdss[0].data, gauss_kernel) max_sdss = result2.max() result2 = result2 / max_sdss
def astropy_smooth(x, window): from astropy.convolution import convolve, Box1DKernel kernel = Box1DKernel(window) smoothed = convolve(x, kernel, boundary="extend", normalize_kernel=True) return smoothed
def skyview_stamp(ra, decl, survey='DSS2 Red', scaling='Linear', flip=True, convolvewith=None, forcefetch=False, cachedir='~/.astrobase/stamp-cache', timeout=10.0, retry_failed=False, savewcsheader=True, verbose=False): '''This is the internal version of the astroquery_skyview_stamp function. Why this exists: - SkyView queries don't accept timeouts (should put in a PR for this) - we can drop the dependency on astroquery (but add another on requests) flip = True will flip the image top to bottom. if convolvewith is an astropy.convolution kernel: http://docs.astropy.org/en/stable/convolution/kernels.html this will return the stamp convolved with that kernel. This can be useful to see effects of wide-field telescopes (like the HATNet and HATSouth lenses) degrading the nominal 1 arcsec/px of DSS, causing blending of targets and any variability. cachedir points to the astrobase stamp-cache directory. ''' stampdict = get_stamp(ra, decl, survey=survey, scaling=scaling, forcefetch=forcefetch, cachedir=cachedir, timeout=timeout, retry_failed=retry_failed, verbose=verbose) # # DONE WITH FETCHING STUFF # if stampdict: # open the frame stampfits = pyfits.open(stampdict['fitsfile']) header = stampfits[0].header frame = stampfits[0].data stampfits.close() # finally, we can process the frame if flip: frame = np.flipud(frame) if verbose: LOGINFO('fetched stamp successfully for (%.3f, %.3f)' % (ra, decl)) if convolvewith: convolved = aconv.convolve(frame, convolvewith) if savewcsheader: return frame, header else: return frame else: if savewcsheader: return frame, header else: return frame else: LOGERROR('could not fetch the requested stamp for ' 'coords: (%.3f, %.3f) from survey: %s and scaling: %s' % (ra, decl, survey, scaling)) return None
def plot_background(star, n_peaks=10): """ Creates a plot summarising the results of the fit background routine. Parameters ---------- star : target.Target the main pipeline Target class object n_peaks : int the number of peaks to highlight in the zoomed-in power spectrum Results ------- None """ from pysyd.functions import return_max, max_elements from pysyd.models import harvey fig = plt.figure(figsize=(12, 12)) # Time series data ax1 = fig.add_subplot(3, 3, 1) if star.lc: ax1.plot(star.time, star.flux, 'w-') ax1.set_xlim([min(star.time), max(star.time)]) ax1.set_title(r'$\rm Time \,\, series$') ax1.set_xlabel(r'$\rm Time \,\, [days]$') ax1.set_ylabel(r'$\rm Flux$') # Initial background guesses star.smooth_power = convolve( star.random_pow, Box1DKernel(int(np.ceil(star.fitbg['box_filter'] / star.resolution)))) ax2 = fig.add_subplot(3, 3, 2) ax2.plot(star.frequency, star.random_pow, c='lightgrey', zorder=0, alpha=0.5) ax2.plot(star.frequency[star.frequency < star.maxpower[0]], star.random_pow[star.frequency < star.maxpower[0]], 'w-', zorder=1) ax2.plot(star.frequency[star.frequency > star.maxpower[1]], star.random_pow[star.frequency > star.maxpower[1]], 'w-', zorder=1) ax2.plot(star.frequency[star.frequency < star.maxpower[0]], star.smooth_power[star.frequency < star.maxpower[0]], 'r-', linewidth=0.75, zorder=2) ax2.plot(star.frequency[star.frequency > star.maxpower[1]], star.smooth_power[star.frequency > star.maxpower[1]], 'r-', linewidth=0.75, zorder=2) for r in range(star.nlaws): ax2.plot(star.frequency, harvey(star.frequency, [star.a_orig[r], star.b_orig[r], star.noise]), color='blue', linestyle=':', linewidth=1.5, zorder=4) ax2.plot(star.frequency, harvey(star.frequency, star.pars, total=True), color='blue', linewidth=2., zorder=5) ax2.errorbar(star.bin_freq, star.bin_pow, yerr=star.bin_err, color='lime', markersize=0., fillstyle='none', ls='None', marker='D', capsize=3, ecolor='lime', elinewidth=1, capthick=2, zorder=3) for m, n in zip(star.mnu_orig, star.a_orig): ax2.plot(m, n, color='blue', fillstyle='none', mew=3.0, marker='s', markersize=5.0) ax2.axvline(star.maxpower[0], color='darkorange', linestyle='dashed', linewidth=2.0, zorder=1, dashes=(5, 5)) ax2.axvline(star.maxpower[1], color='darkorange', linestyle='dashed', linewidth=2.0, zorder=1, dashes=(5, 5)) ax2.axhline(star.noise, color='blue', linestyle='dashed', linewidth=1.5, zorder=3, dashes=(5, 5)) ax2.set_xlim([min(star.frequency), max(star.frequency)]) ax2.set_ylim([min(star.power), max(star.power) * 1.25]) ax2.set_title(r'$\rm Initial \,\, guesses$') ax2.set_xlabel(r'$\rm Frequency \,\, [\mu Hz]$') ax2.set_ylabel(r'$\rm Power \,\, [ppm^{2} \mu Hz^{-1}]$') ax2.set_xscale('log') ax2.set_yscale('log') # Fitted background ax3 = fig.add_subplot(3, 3, 3) ax3.plot(star.frequency, star.random_pow, c='lightgrey', zorder=0, alpha=0.5) ax3.plot(star.frequency[star.frequency < star.maxpower[0]], star.random_pow[star.frequency < star.maxpower[0]], 'w-', linewidth=0.75, zorder=1) ax3.plot(star.frequency[star.frequency > star.maxpower[1]], star.random_pow[star.frequency > star.maxpower[1]], 'w-', linewidth=0.75, zorder=1) ax3.plot(star.frequency[star.frequency < star.maxpower[0]], star.smooth_power[star.frequency < star.maxpower[0]], 'r-', linewidth=0.75, zorder=2) ax3.plot(star.frequency[star.frequency > star.maxpower[1]], star.smooth_power[star.frequency > star.maxpower[1]], 'r-', linewidth=0.75, zorder=2) for r in range(star.nlaws): ax3.plot( star.frequency, harvey(star.frequency, [star.pars[2 * r], star.pars[2 * r + 1], star.pars[-1]]), color='blue', linestyle=':', linewidth=1.5, zorder=4) ax3.plot(star.frequency, harvey(star.frequency, star.pars, total=True), color='blue', linewidth=2.0, zorder=5) ax3.errorbar(star.bin_freq, star.bin_pow, yerr=star.bin_err, color='lime', markersize=0.0, fillstyle='none', ls='None', marker='D', capsize=3, ecolor='lime', elinewidth=1, capthick=2, zorder=3) ax3.axvline(star.maxpower[0], color='darkorange', linestyle='dashed', linewidth=2.0, zorder=1, dashes=(5, 5)) ax3.axvline(star.maxpower[1], color='darkorange', linestyle='dashed', linewidth=2.0, zorder=1, dashes=(5, 5)) ax3.axhline(star.pars[-1], color='blue', linestyle='dashed', linewidth=1.5, zorder=3, dashes=(5, 5)) ax3.plot(star.frequency, star.pssm, color='yellow', linewidth=2.0, linestyle='dashed', zorder=6) ax3.set_xlim([min(star.frequency), max(star.frequency)]) ax3.set_ylim([min(star.power), max(star.power) * 1.25]) ax3.set_title(r'$\rm Fitted \,\, model$') ax3.set_xlabel(r'$\rm Frequency \,\, [\mu Hz]$') ax3.set_ylabel(r'$\rm Power \,\, [ppm^{2} \mu Hz^{-1}]$') ax3.set_xscale('log') ax3.set_yscale('log') # Smoothed power excess w/ gaussian ax4 = fig.add_subplot(3, 3, 4) ax4.plot(star.region_freq, star.region_pow, 'w-', zorder=0) idx = return_max(star.region_freq, star.region_pow, index=True) ax4.plot([star.region_freq[idx]], [star.region_pow[idx]], color='red', marker='s', markersize=7.5, zorder=0) ax4.axvline([star.region_freq[idx]], color='white', linestyle='--', linewidth=1.5, zorder=0) ax4.plot(star.new_freq, star.numax_fit, 'b-', zorder=3) ax4.axvline(star.exp_numax, color='blue', linestyle=':', linewidth=1.5, zorder=2) ax4.plot([star.exp_numax], [max(star.numax_fit)], color='b', marker='D', markersize=7.5, zorder=1) ax4.set_title(r'$\rm Smoothed \,\, bg$-$\rm corrected \,\, PS$') ax4.set_xlabel(r'$\rm Frequency \,\, [\mu Hz]$') ax4.set_xlim([min(star.region_freq), max(star.region_freq)]) # Background-corrected power spectrum with n highest peaks star.freq = star.frequency[star.params[star.name]['ps_mask']] star.psd = star.bg_corr_smooth[star.params[star.name]['ps_mask']] peaks_f, peaks_p = max_elements(star.freq, star.psd, n_peaks) ax5 = fig.add_subplot(3, 3, 5) ax5.plot(star.freq, star.psd, 'w-', zorder=0, linewidth=1.0) ax5.scatter(peaks_f, peaks_p, s=25.0, edgecolor='r', marker='s', facecolor='none', linewidths=1.0) ax5.set_title(r'$\rm Bg$-$\rm corrected \,\, PS$') ax5.set_xlabel(r'$\rm Frequency \,\, [\mu Hz]$') ax5.set_ylabel(r'$\rm Power$') ax5.set_xlim([min(star.region_freq), max(star.region_freq)]) ax5.set_ylim([ min(star.psd) - 0.025 * (max(star.psd) - min(star.psd)), max(star.psd) + 0.1 * (max(star.psd) - min(star.psd)) ]) sig = 0.35 * star.exp_dnu / 2.35482 weights = 1. / (sig * np.sqrt(2. * np.pi)) * np.exp( -(star.lag - star.exp_dnu)**2. / (2. * sig**2)) new_weights = weights / max(weights) # ACF for determining dnu ax6 = fig.add_subplot(3, 3, 6) ax6.plot(star.lag, star.auto, 'w-', zorder=0, linewidth=1.) ax6.scatter(star.peaks_l, star.peaks_a, s=30.0, edgecolor='r', marker='^', facecolor='none', linewidths=1.0) ax6.axvline(star.exp_dnu, color='red', linestyle=':', linewidth=1.5, zorder=5) ax6.axvline(star.obs_dnu, color='lime', linestyle='--', linewidth=1.5, zorder=2) ax6.scatter(star.best_lag, star.best_auto, s=45.0, edgecolor='lime', marker='s', facecolor='none', linewidths=1.0) ax6.plot(star.zoom_lag, star.zoom_auto, 'r-', zorder=5, linewidth=1.0) ax6.plot(star.lag, new_weights, c='yellow', linestyle=':', zorder=0, linewidth=1.0) ax6.set_title(r'$\rm ACF \,\, for \,\, determining \,\, \Delta\nu$') ax6.set_xlabel(r'$\rm Frequency \,\, separation \,\, [\mu Hz]$') ax6.set_xlim([min(star.lag), max(star.lag)]) ax6.set_ylim([ min(star.auto) - 0.05 * (max(star.auto) - min(star.auto)), max(star.auto) + 0.1 * (max(star.auto) - min(star.auto)) ]) # dnu fit ax7 = fig.add_subplot(3, 3, 7) ax7.plot(star.zoom_lag, star.zoom_auto, 'w-', zorder=0, linewidth=1.0) ax7.axvline(star.obs_dnu, color='lime', linestyle='--', linewidth=1.5, zorder=2) ax7.plot(star.new_lag, star.dnu_fit, color='lime', linewidth=1.5) ax7.axvline(star.exp_dnu, color='red', linestyle=':', linewidth=1.5, zorder=5) ax7.set_title(r'$\rm \Delta\nu \,\, fit$') ax7.set_xlabel(r'$\rm Frequency \,\, separation \,\, [\mu Hz]$') ax7.annotate(r'$\Delta\nu = %.2f$' % star.obs_dnu, xy=(0.025, 0.85), xycoords="axes fraction", fontsize=18, color='lime') ax7.set_xlim([min(star.zoom_lag), max(star.zoom_lag)]) if star.fitbg['interp_ech']: interpolation = 'bilinear' else: interpolation = 'none' # echelle diagram ax8 = fig.add_subplot(3, 3, 8) ax8.imshow(star.ech, extent=star.extent, interpolation=interpolation, aspect='auto', origin='lower', cmap=plt.get_cmap('viridis')) ax8.axvline([star.obs_dnu], color='white', linestyle='--', linewidth=1.0, dashes=(5, 5)) ax8.set_title(r'$\rm \grave{E}chelle \,\, diagram$') ax8.set_xlabel(r'$\rm \nu \,\, mod \,\, %.2f \,\, [\mu Hz]$' % star.obs_dnu) ax8.set_ylabel(r'$\rm \nu \,\, [\mu Hz]$') ax8.set_xlim([0.0, 2.0 * star.obs_dnu]) ax8.set_ylim([star.maxpower[0], star.maxpower[1]]) ax9 = fig.add_subplot(3, 3, 9) ax9.plot(star.xax, star.yax, color='white', linestyle='-', linewidth=0.75) ax9.set_title(r'$\rm Collapsed \,\, \grave{e}chelle \,\, diagram$') ax9.set_xlabel(r'$\rm \nu \,\, mod \,\, %.2f \,\, [\mu Hz]$' % star.obs_dnu) ax9.set_ylabel(r'$\rm Collapsed \,\, power$') ax9.set_xlim([0.0, 2.0 * star.obs_dnu]) ax9.set_ylim([ min(star.yax) - 0.025 * (max(star.yax) - min(star.yax)), max(star.yax) + 0.05 * (max(star.yax) - min(star.yax)) ]) plt.tight_layout() if star.params['save']: if star.fitbg['interp_ech']: plt.savefig('%sbackground_smooth_echelle.png' % star.params[star.name]['path'], dpi=300) else: plt.savefig('%sbackground.png' % star.params[star.name]['path'], dpi=300) if star.params['show']: plt.show() plt.close()
dataset.OWA = OWA # fileprefix="pyklip_parallelizedRDItest" # parallelized.klip_dataset(dataset, outputdir=dir_test + "test_results/", fileprefix=fileprefix, annuli=annuli, # subsections=subsections, numbasis=numbasis, maxnumbasis=maxnumbasis, mode="RDI", # aligned_center=aligned_center, highpass=False, psf_library=psflib) # fileprefix="pyklip_parallelizedADItest" # parallelized.klip_dataset(dataset, outputdir=dir_test + "test_results/", fileprefix=fileprefix, annuli=annuli, # subsections=subsections, numbasis=numbasis, maxnumbasis=maxnumbasis, mode="ADI", # aligned_center=aligned_center, highpass=False) # create a phony disk model and convovle it by the instrument psf phony_disk_model = make_phony_disk(281) model_convolved = convolve(phony_disk_model, instrument_psf, boundary="wrap") fits.writeto( dir_test + "test_results/psf.fits", instrument_psf, overwrite=True, ) fits.writeto( dir_test + "test_results/disk_model_before.fits", phony_disk_model, overwrite=True, ) fits.writeto( dir_test + "test_results/disk_model_after.fits",
def correct_MRS(input_model, straylight_model): """ Short Summary ------------- Corrects the MIRI MRS data for straylight Uses the straylight reference file Parameter ---------- input_model: data model object science data to be corrected straylight_model: holds the straylight mask for the correction Returns ------- output: data model object straylight-subtracted science data """ # Save some data parameterss for easy use later nrows, ncols = input_model.data.shape # mask is either 1 or 0 mask = straylight_model.data x = float('nan') # The straylight mask has values of 1 and 0. The straylight task uses data # in-between the slices (also called slice gaps) of the MRS data to correct # the science data in the slices. In the mask the pixels found in the gaps # have a value of 1 and the science pixels have a value of 0. # Create output as a copy of the input science data model # sci_mask is the input science image * mask # science regions = 0 (reference pixel are also = 0) output = input_model.copy() # this is used in algorithm to # find the straylight correction. #_________________________________________________________________ # if there are nans remove them because they mess up the correction index_inf = np.isinf(output.data).nonzero() output.data[index_inf] = 0.0 mask[index_inf] = 0 # flag associated mask so we do not use any # slice gaps that are nans, now data=0 . #_________________________________________________________________ # flag bad pixels mask_dq = input_model.dq.copy() # * mask # find DQ flags of the gap values all_flags = (dqflags.pixel['DEAD'] + dqflags.pixel['HOT']) # where are pixels set to any one of the all_flags cases testflags = np.bitwise_and(mask_dq, all_flags) # where are testflags ne 0 and mask == 1 bad_flags = np.where(testflags != 0) mask[bad_flags] = 0 #_________________________________________________________________ sci_mask = output.data * mask #sci_maskcontains 0's in science regions of detector. straylight_image = output.data * 0.0 #We Want Sci mask smoothed for GAP region with 3 X 3 box car filter # Handle edge cases for boxcar smoothing, by determining the # boxcar smoothing of the mask. sci_ave = convolve(sci_mask, Box2DKernel(3)) mask_ave = convolve(mask, Box2DKernel(3)) # catch /0 cases index = np.where(mask_ave == 0) # zero catches cases that would be #/0 # near edges values are 0.3333 0.6667 1 sci_ave[index] = 0 mask_ave[index] = 1 sci_smooth = sci_ave / mask_ave x = np.arange(ncols) # Loop over each row (0 to 1023) for j in range(nrows): row_mask = mask[j, :] if (np.sum(row_mask) > 0): # find the locations of slice gaps #determine the data in the slice gaps yuse = sci_smooth[j, np.where(row_mask == 1)] #find the x locations of the slice gaps xuse = x[np.where(row_mask == 1)] #if(j ==1): # print 'row ',j+1,yuse.shape,yuse # print 'xuse',xuse,xuse.shape,type(xuse) #find data in same gap area nn = len(xuse) #dx difference in adjacent slice gaps pixels --> used # to find x limits of each gap dx = xuse[1:nn] - xuse[0:nn - 1] # Find the number of slice gaps in row idx = np.asarray(np.where(dx > 1)) ngroups = len(idx[0]) + 1 # xlimits are the x values that mark limits of a slice gaps xlimits = np.zeros(ngroups + 1) i = 1 xlimits[0] = xuse[0] for index in idx[0]: xlimits[i] = xuse[index] i = i + 1 xlimits[ngroups] = xuse[nn - 1] #+1 xg = np.zeros(ngroups) yg = np.zeros(ngroups) # loop over all slice gaps in a row # find the mean y straylight value for each slice gaps # also find the mean x value for this slice gap for i in range(ngroups): lower_limit = xlimits[i] upper_limit = xlimits[i + 1] igap = np.asarray( np.where( np.logical_and(xuse > lower_limit, xuse <= upper_limit))) ymean = np.mean(yuse[0, igap[0]]) xmean = np.mean(xuse[igap[0]]) yg[i] = ymean xg[i] = xmean # else entire row is zero else: xg = np.array([0, 1032]) yg = np.array([0, 0]) #using mean y value in slice gaps and x location of ymean #interpolate what straylight contribution based on yg and xg # for all points in row for k in x: if (x[k] >= xg[0] and x[k] <= xg[-1]): ynew = np.interp(x[k], xg, yg) else: if x[k] < xg[0]: ynew = yg[0] + (x[k] - xg[0]) * (yg[1] - yg[0]) / (xg[1] - xg[0]) elif x[k] > xg[-1]: ynew = yg[-1] + (x[k] - xg[-1]) * (yg[-1] - yg[-2]) / ( xg[-1] - xg[-2]) straylight_image[j, k] = ynew # end loop over rows straylight_image[straylight_image < 0] = 0 # pull out the science region (1024 pixel/row) to do boxcar smoothing on simage = convolve(straylight_image, Box2DKernel(25)) # remove the straylight correction for the reference pixels simage[:, 1028:1032] = 0.0 simage[:, 0:4] = 0.0 output.data = output.data - simage return output
def ppxf_single(object_id, z_init, lambda_spec, galaxy_lin, error_lin, cars_model, emsub_specfile=None, plotfile=None, outfile=None, outfile_spec=None, mpoly=None, apoly=None, reflines=None): # Speed of light c = 299792.458 #h_spec = spec_hdu[0].header #Ang_air = h_spec['CRVAL3'] + np.arange(0,h_spec['CDELT3']*(h_spec['NAXIS3']),h_spec['CDELT3']) #s = 10**4/Ang_air #n = 1 + 0.00008336624212083 + 0.02408926869968 / (130.1065924522 - s**2) + 0.000159740894897 / (38.92568793293 - s**2) #lambda_spec = Ang_air*n #wave = h_spec['CRVAL3'] + np.arange(0,h_spec['CDELT3']*(h_spec['NAXIS3']),h_spec['CDELT3']) #lambda_spec = vactoair(wave) #lambda_spec = h_spec['CRVAL3'] + np.arange(0,h_spec['CDELT3']*(h_spec['NAXIS3']),h_spec['CDELT3']) # Crop to finite use = (np.isfinite(galaxy_lin) & (galaxy_lin > 0.0)) # Making a "use" vector use_indices = np.arange(galaxy_lin.shape[0])[use] galaxy_lin = (galaxy_lin[use_indices.min():(use_indices.max() + 1)])[2:-3] error_lin = (error_lin[use_indices.min():(use_indices.max() + 1)])[2:-3] lambda_spec = (lambda_spec[use_indices.min():(use_indices.max() + 1)])[2:-3] lamRange_gal = np.array([np.min(lambda_spec), np.max(lambda_spec)]) # New resolution estimate = 0.9 \AA (sigma), converting from sigma to FWHM FWHM_gal = 2.355 * (np.max(lambda_spec) - np.min(lambda_spec)) / len(lambda_spec) print('FWHM', FWHM_gal) lamRange_gal = lamRange_gal / ( 1 + float(z_init)) # Compute approximate restframe wavelength range FWHM_gal = FWHM_gal / (1 + float(z_init)) # Adjust resolution in Angstrom sigma_gal = FWHM_gal / (2.3548 * 4500.0) * c # at ~4500 \AA # log rebinning for the fits galaxy, logLam_gal, velscale = util.log_rebin(np.around(lamRange_gal, decimals=3), galaxy_lin, flux=True) noise, logLam_noise, velscale = util.log_rebin(np.around(lamRange_gal,decimals=3), error_lin, \ velscale=velscale, flux=True) # correcting for infinite or zero noise noise[np.logical_or((noise == 0.0), np.isnan(noise))] = 1.0 galaxy[np.logical_or((galaxy < 0.0), np.isnan(galaxy))] = 0.0 if galaxy.shape != noise.shape: galaxy = galaxy[:-1] logLam_gal = logLam_gal[:-1] # Define lamRange_temp and logLam_temp #lamRange_temp, logLam_temp = setup_spectral_library_conroy(velscale[0], FWHM_gal) # Construct a set of Gaussian emission line templates. # Estimate the wavelength fitted range in the rest frame. # gas_templates, line_names, line_wave = util.emission_lines( logLam_gal, lamRange_gal, FWHM_gal) goodpixels = np.arange(galaxy.shape[0]) wave = np.exp(logLam_gal) # crop very red end (only affects a very small subsample) # goodpixels = goodpixels[wave <= 5300] # exclude lines at the edges (where things can go very very wrong :)) include_lines = np.where((line_wave > (wave.min() + 10.0)) & (line_wave < (wave.max() - 10.0))) if line_wave[include_lines[0]].shape[0] < line_wave.shape[0]: line_wave = line_wave[include_lines[0]] line_names = line_names[include_lines[0]] gas_templates = gas_templates[:, include_lines[0]] #reg_dim = stars_templates.shape[1:] reg_dim = gas_templates.shape[1:] templates = gas_templates #np.hstack([gas_templates, gas_templates]) dv = 0 #(logLam_temp[0]-logLam_gal[0])*c # km/s vel = 0 #np.log(z_init + 1)*c # Initial estimate of the galaxy velocity in km/s #z = np.exp(vel/c) - 1 # Relation between velocity and redshift in pPXF # Here the actual fit starts. The best fit is plotted on the screen. # Gas emission lines are excluded from the pPXF fit using the GOODPIXELS keyword. # t = clock() nNLines = gas_templates.shape[1] component = [0] * nNLines start_gas = [vel, 100.] start = start_gas # adopt the same starting value for both gas (BLs and NLs) and stars moments = [ 2 ] # fit (V,sig,h3,h4) for the stars and (V,sig) for the gas' broad and narrow components fixed = None ## Additive polynomial degree if apoly is None: degree = int( np.ceil((lamRange_gal[1] - lamRange_gal[0]) / (100.0 * (1. + float(z_init))))) else: degree = int(apoly) if mpoly is None: mdegree = 3 else: mdegree = int(mpoly) # Trying: sigmas must be kinematically decoupled # #Trying: velocities must be kinematically decoupled #A_ineq = [[0,0,2,0,-1,0]] #b_ineq = [0] bounds_gas = [[-1000, 1000], [0, 1000]] bounds = bounds_gas pp = ppxf.ppxf(templates, galaxy, noise, velscale, start, fixed=fixed, plot=False, moments=moments, mdegree=mdegree, degree=degree, vsyst=dv, reg_dim=reg_dim, goodpixels=goodpixels, bounds=bounds) #component=component, # redshift_to_newtonian: # return (v-astropy.constants.c.to('km/s').value*redshift)/(1.0+redshift) # "v" from above is actually the converted velocity which is # (np.exp(v_out/c) - 1)*c v_gas = pp.sol[0] ev_gas = pp.error[0] conv_vel_gas = (np.exp(pp.sol[0] / c) - 1) * c vel_gas = (1 + z_init) * (conv_vel_gas - c * z_init) sigma_gas = pp.sol[1] #first # is template, second # is the moment esigma_gas = pp.error[1] #*np.sqrt(pp.chi2) zfit_gas = (z_init + 1) * (1 + pp.sol[0] / c) - 1 zfit_stars = z_init ezfit_gas = (z_init + 1) * pp.error[0] * np.sqrt(pp.chi2) / c if plotfile is not None: # ### All of the rest of this plots and outputs the results of the fit ### Feel free to comment anything out at will # maskedgalaxy = np.copy(galaxy) lowSN = np.where(noise > (0.9 * np.max(noise))) maskedgalaxy[lowSN] = np.nan wave = np.exp(logLam_gal) * (1. + z_init) / (1. + zfit_stars) fig = plt.figure(figsize=(12, 7)) ax1 = fig.add_subplot(211) # plotting smoothed spectrum smoothing_fact = 3 ax1.plot(wave, convolve(maskedgalaxy, Box1DKernel(smoothing_fact)), color='Gray', linewidth=0.5) ax1.plot(wave[goodpixels], convolve(maskedgalaxy[goodpixels], Box1DKernel(smoothing_fact)), 'k', linewidth=1.) label = "Best fit template from high res Conroy SSPs + emission lines at z={0:.3f}".format( zfit_stars) # overplot stellar templates alone ax1.plot(wave, pp.bestfit, 'r', linewidth=1.0, alpha=0.75, label=label) ax1.set_ylabel('Flux') ax1.legend(loc='upper right', fontsize=10) ax1.set_title(object_id) xmin, xmax = ax1.get_xlim() ax2 = fig.add_subplot(413, sharex=ax1, sharey=ax1) # plotting emission lines if included in the fit gas = pp.matrix[:, -nNLines:].dot(pp.weights[-nNLines:]) ax2.plot(wave, gas, 'b', linewidth=2,\ label = '$\sigma_{gas}$'+'={0:.0f}$\pm${1:.0f} km/s'.format(sigma_gas, esigma_gas)+', $V_{gas}$'+'={0:.0f}$\pm${1:.0f} km/s'.format(v_gas, ev_gas)) # overplot emission lines alone cars_model = (cars_model[use_indices.min():(use_indices.max() + 1)])[2:-3] ax2.plot(np.array(lambda_spec)/(1+z_init), cars_model, color='orange', linewidth=1,\ label = 'CARS Model') #(lambda_spec[use_indices.min():(use_indices.max()+1)])[2:-3] stars = pp.bestfit - gas #if (ymax > 3.0*np.median(stars)): ymax = 3.0*np.median(stars) #if (ymin < -0.5): ymin = -0.5 ax2.set_ylabel('Best Fits') ax2.legend(loc='upper left', fontsize=10) # Plotting the residuals ax3 = fig.add_subplot(817, sharex=ax1) ax3.plot(wave[goodpixels], (convolve(maskedgalaxy, Box1DKernel(smoothing_fact)) - pp.bestfit)[goodpixels], 'k', label='Fit Residuals') #ax3.set_yticks([-0.5,0,0.5]) ax3.set_ylabel('Residuals') ax4 = fig.add_subplot(818, sharex=ax1) ax4.plot(wave, noise, 'k', label='Flux Error') ax4.set_ylabel('Noise') ax4.set_xlabel('Rest Frame Wavelength [$\AA$]') #ax4.set_yticks(np.arange(0,0.5,0.1)) '''if reflines is not None: for i,w,label in zip(range(len(reflines)),reflines['wave'],reflines['label']): if ((w > xmin) and (w < xmax)): # ax1.text(w,ymin+(ymax-ymin)*(0.03+0.08*(i % 2)),'$\mathrm{'+label+'}$',fontsize=10,\ # horizontalalignment='center',\ # bbox=dict(boxstyle='round', facecolor='white', alpha=0.5)) print(label.decode("utf-8")) ax1.text(w,ymin+(ymax-ymin)*(0.03+0.08*(i % 2)),'$\mathrm{'+label.decode("utf-8")+'}$',fontsize=10,\ horizontalalignment='center',\ bbox=dict(boxstyle='round', facecolor='white', alpha=0.5)) ax1.plot([w,w],[ymin,ymax],':k',alpha=0.5)''' fig.subplots_adjust(hspace=0.05) plt.setp([a.get_xticklabels() for a in fig.axes[:-1]], visible=False) #print('Saving figure to {0}'.format(plotfile)) ax1.set_xlim([6450, 6750]) ax2.set_xlim([6450, 6750]) #ymin, ymax = ax1.get_ylim([]) plt.savefig(plotfile, dpi=150) plt.close() return v_gas, vel_gas, sigma_gas, pp.chi2 # print('# id z_stars ez_stars sigma_stars esigma_stars z_gas ez_gas sigma_gas esigma_gas SN_median SN_rf_4000 SN_obs_8030 chi2dof') print('{0:d} {1:.6f} {2:.6f} {3:.1f} {4:.1f} {5:.6f} {6:.6f} {7:.1f} {8:.1f} {9:.1f} {10:.1f} {11:.1f} {12:.2f}\n'.format(\ object_id,zfit_stars,ezfit_stars, sigma_stars,esigma_stars,\ zfit_gas, ezfit_gas, sigma_gas, esigma_gas, SN_median, SN_rf_4000, SN_obs_8030, pp.chi2)) ## This prints the fit parameters to an open file object called outfile if outfile is not None: outfile.write('{0:d} {1:d} {2:.6f} {3:.6f} {4:.1f} {5:.1f} {6:.6f} {7:.6f} {8:.1f} {9:.1f} {10:.1f} {11:.1f} {12:.1f} {13:.2f}\n'.format(\ object_id, row2D, zfit_stars, ezfit_stars, sigma_stars,esigma_stars,\ zfit_gas, ezfit_gas, sigma_gas, esigma_gas, SN_median, SN_rf_4000, SN_obs_8030, pp.chi2)) ## This outputs the spectrum and best-fit model to an open file object called outfile_spec if outfile_spec is not None: outfile_spec.write( '# l f ef f_stars f_gas f_model_tot used_in_fit add_poly mult_poly\n' ) for i in np.arange(wave.shape[0]): isgood = 0 if goodpixels[goodpixels == i].shape[0] == 1: isgood = 1 outfile_spec.write( '{0:0.4f} {1:0.4f} {2:0.4f} {3:0.4f} {4:0.4f} {5:0.4f} {6} {7:0.4f} {8:0.4f}\n' .format(wave[i], galaxy[i], noise[i], stars[i], gas[i], pp.bestfit[i], isgood, add_polynomial[i], mult_polynomial[i])) # ## This outputs the best-fit emission-subtracted spectrum to a fits file # ## but I've commented it out since you are unlikely to need this! # if emsub_specfile is not None: # wave = np.exp(logLam_gal)*(1.+z_init) # if include_gas: # emsub = galaxy - gas # else: # emsub = galaxy # col1 = fits.Column(name='wavelength', format='E', array=wave) # col2 = fits.Column(name='flux',format='E',array=galaxy) # col3 = fits.Column(name='error',format='E',array=noise) # col4 = fits.Column(name='flux_emsub',format='E',array=emsub) # cols = fits.ColDefs([col1,col2,col3,col4]) # tbhdu = fits.BinTableHDU.from_columns(cols) # # delete old file if it exists # if os.path.isfile(emsub_specfile): os.remove(emsub_specfile) # tbhdu.writeto(emsub_specfile) # return zfit_stars, ezfit_stars, sigma_stars, esigma_stars, zfit_gas, ezfit_gas, \ # sigma_gas, esigma_gas, SN_median, SN_rf_4000, SN_obs_8030, pp.chi2 return zfit_stars, sigma_stars, sigma_blr, wave, pp.bestfit
#plt.plot(d[:,1], d[:,2]*0.95316816783, label = 'GCM', color = '0.1') #multiplied by correction factor for rp/rs (Vivien assuemd 0.1055) #plt.ylim(0.0, 1.8e-3) #plt.xlim(0.75, 1.7) plt.ylim(0.0, 4.8e-3) plt.xlim(0.75, 5.7) #plt.gca().annotate('TiO features', xy=(1.05, 0.0008), xytext=(0.8, 0.0005), arrowprops=dict(facecolor='black', shrink=0.05),) #plt.gca().annotate('', xy=(0.97, 0.00095), xytext=(0.95, 0.0006), arrowprops=dict(facecolor='black', shrink=0.05),) g = Gaussian1DKernel(stddev=50) offset = 0.0000 d = np.genfromtxt("wasp33b_from_Caroline/wasp33b_rfacv1.0_m0.0_co1.0nc.flx") plt.plot(d[:, 0], convolve(d[:, 1], g, boundary='extend') + offset, label="forward model, rfacv1.0_m0.0") d = np.genfromtxt("wasp33b_from_Caroline/wasp33b_rfacv0.85_m0.0_co1.0nc.flx") plt.plot(d[:, 0], convolve(d[:, 1], g, boundary='extend') + offset, label="forward model, rfacv0.85_m0.0") #d = np.genfromtxt("wasp33b_m0.0_co1.0nc.spec") #plt.plot(d[:,0], convolve(d[:,1], g, boundary = 'extend') + offset, label = "forward model, with TiO") #d = np.genfromtxt("wasp33b_m0.0_co1.0nc_noTiO.spec") #plt.plot(d[:,0], convolve(d[:,1], g, boundary = 'extend') + offset, label = "forward model, no TiO") plt.errorbar(4.5, 4250e-6, 160e-6, fmt='xk') plt.errorbar(3.6, 3506e-6, 173e-6, fmt='xk')
def main(): """ # Script to get lineflux """ # Get extraction data = np.genfromtxt("../data/spectroscopy/NIRext.dat", dtype=None) # data = np.genfromtxt("../data/NIROB4skysubstdext.dat", dtype=None) # print(np.std([18, 31, 38, 20])) # exit() wl = data[:, 1] flux = data[:, 2] error = data[:, 3] error[error > 1e-15] = np.median(error) # Load synthetic sky sky_model = fits.open("../data/spectroscopy/NIRskytable.fits") wl_sky = 10 * (sky_model[1].data.field('lam')) # In nm # Convolve to observed grid f = interpolate.interp1d(wl_sky, convolve(sky_model[1].data.field('flux'), Gaussian1DKernel(stddev=3)), bounds_error=False, fill_value=np.nan) # f = interpolate.interp1d(wl_sky, sky_model[1].data.field('flux'), bounds_error=False, fill_value=np.nan) flux_sky = f(wl) flux[(wl > 21055) & (wl < 21068)] = np.nan flux[(wl > 21098) & (wl < 21102)] = np.nan flux[(wl > 21109) & (wl < 21113)] = np.nan m = (flux_sky < 9000) & ~np.isnan(flux) g = interpolate.interp1d(wl[m], flux[m], bounds_error=False, fill_value=np.nan) flux = g(wl) mask = (wl > convert_air_to_vacuum(21076) - 9) & ( wl < convert_air_to_vacuum(21076) + 9) # mask = (wl > 21020) & (wl < 21150) F_ha = np.trapz(flux[mask], x=wl[mask]) print("Total %0.1e" % F_ha) F_ha_err = np.sqrt(np.trapz((error**2.)[mask], x=wl[mask])) print("Total %0.1e +- %0.1e" % (F_ha, F_ha_err)) # exit() # F_ha = 4.1e-17 dL = cosmo.luminosity_distance(2.211).to(u.cm).value L_ha = F_ha * 4 * np.pi * dL**2 L_ha_err = F_ha_err * 4 * np.pi * dL**2 SFR = 7.9e-42 * L_ha SFR_err = 7.9e-42 * L_ha_err print(SFR, SFR_err) # exit() # print(len(wl_sky), len(wl)) v_rot = (((16092 - 16068) / 16080) * 3e5) / 2 * (u.km / u.s) print(v_rot * 2) M = v_rot**2 * ((7 / 2) * 0.21 * 8.46597 * u.kpc) / c.G print("%0.4e" % M.to(u.M_sun).value) # flux[flux_sky > 10000] = np.nan pl.plot(wl, flux, label="Spectrum") pl.plot(wl[mask], flux[mask], label="Integration limits") pl.plot(wl, flux_sky * 1e-22, label="Sky spectrum") pl.errorbar(wl, flux, yerr=error, fmt=".k", capsize=0, elinewidth=0.5, ms=3, label="SFR = " + str(np.around(SFR, 0)) + " +-" + str(np.around(SFR_err, 0))) pl.errorbar(1, 1, yerr=1, fmt=".k", capsize=0, elinewidth=0.5, ms=3, label=r"f$_{H\alpha}$ = %0.1e +- %0.1e" % (F_ha, F_ha_err)) pl.xlim(21000, 21150) pl.ylim(-0.5e-17, 3e-17) # pl.show() # Save figure for tex pl.legend() pl.savefig("../figures/Ha_flux.pdf", dpi="figure") pl.show()