Beispiel #1
0
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 
Beispiel #2
0
    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
Beispiel #3
0
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()
Beispiel #5
0
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
Beispiel #8
0
    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)))
Beispiel #10
0
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))
Beispiel #11
0
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
Beispiel #12
0
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)
Beispiel #13
0
    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')
Beispiel #14
0
def conv(img):
    kernel_file=pyfits.open(root+kfile)
    kernel=kernel_file[0].data

    new=convolve(img,kernel)

    return new
Beispiel #15
0
    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
Beispiel #16
0
    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)
Beispiel #17
0
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)
Beispiel #18
0
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
Beispiel #19
0
	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)
Beispiel #21
0
    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
Beispiel #23
0
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
Beispiel #25
0
    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
Beispiel #26
0
    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)
Beispiel #30
0
    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())
Beispiel #31
0
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")
Beispiel #33
0
    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])
Beispiel #34
0
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)
Beispiel #35
0
    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
Beispiel #37
0
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
Beispiel #38
0
    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')
Beispiel #39
0
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
Beispiel #40
0
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
Beispiel #42
0
def find_lyman_break(SpectralDataObject):
    #smooth the data first because its noisy
    gauss_kernel = Gaussian1DKernel(5)
    smoothed_data = convolve(SpectralDataObject, gauss_kernel)
Beispiel #43
0
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
Beispiel #44
0
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
Beispiel #45
0
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)
Beispiel #46
0
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
Beispiel #47
0
    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()
Beispiel #48
0
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
Beispiel #49
0
                    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 = [
Beispiel #50
0
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
Beispiel #52
0
        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
Beispiel #53
0
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
Beispiel #54
0
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
Beispiel #55
0
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()
Beispiel #56
0
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",
Beispiel #57
0
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
Beispiel #58
0
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
Beispiel #59
0
#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')
Beispiel #60
0
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()