示例#1
0
def find_xy_peak(img, center=None, sigma=3.0):
    """ Find the center of the peak of offsets
    """
    # find level of noise in histogram
    istats = imagestats.ImageStats(img,
                                   nclip=1,
                                   fields='stddev,mode,mean,max,min')

    if istats.stddev == 0.0:
        istats = imagestats.ImageStats(img, fields='stddev,mode,mean,max,min')

    imgsum = img.sum()

    # clip out all values below mean+3*sigma from histogram
    imgc = img[:, :].copy()
    imgc[imgc < istats.mode + istats.stddev * sigma] = 0.0

    # identify position of peak
    yp0, xp0 = np.where(imgc == imgc.max())

    # Perform bounds checking on slice from img
    ymin = max(0, int(yp0[0]) - 3)
    ymax = min(img.shape[0], int(yp0[0]) + 4)
    xmin = max(0, int(xp0[0]) - 3)
    xmax = min(img.shape[1], int(xp0[0]) + 4)

    # take sum of at most a 7x7 pixel box around peak
    xp_slice = (slice(ymin, ymax), slice(xmin, xmax))
    yp, xp = center_of_mass(img[xp_slice])

    if np.isnan(xp) or np.isnan(yp):
        xp = 0.0
        yp = 0.0
        flux = 0.0
        zpqual = None

    else:
        xp += xp_slice[1].start
        yp += xp_slice[0].start

        # compute S/N criteria for this peak: flux/sqrt(mean of rest of array)
        flux = imgc[xp_slice].sum()
        delta_size = float(img.size - imgc[xp_slice].size)
        if delta_size == 0:
            delta_size = 1
        delta_flux = float(imgsum - flux)
        if flux > imgc[xp_slice].max():
            delta_flux = flux - imgc[xp_slice].max()
        else:
            delta_flux = flux
        zpqual = flux / np.sqrt(delta_flux / delta_size)
        if np.isnan(zpqual) or np.isinf(zpqual):
            zpqual = None

        if center is not None:
            xp -= center[0]
            yp -= center[1]
        flux = imgc[xp_slice].max()

    return xp, yp, flux, zpqual
示例#2
0
def _computeSky(image, skypars, memmap=False):
    """
    Compute the sky value for the data array passed to the function
    image is a fits object which contains the data and the header
    for one image extension

    skypars is passed in as paramDict

    """
    #this object contains the returned values from the image stats routine
    _tmp = imagestats.ImageStats(image.data,
                                 fields=skypars['skystat'],
                                 lower=skypars['skylower'],
                                 upper=skypars['skyupper'],
                                 nclip=skypars['skyclip'],
                                 lsig=skypars['skylsigma'],
                                 usig=skypars['skyusigma'],
                                 binwidth=skypars['skywidth'])

    _skyValue = _extractSkyValue(_tmp, skypars['skystat'].lower())
    log.info("    Computed sky value/pixel for %s: %s " %
             (image.rootname, _skyValue))

    del _tmp

    return _skyValue
示例#3
0
def getskysigma(filelist, usemode=False, nclip=3):
    """ Compute the median sky noise for the given image or list of images.
    The default uses the skysigma algorithm as stated in the drizzlepac manual (v1.0, 2012)
    instead of the one implemented in drizzlepac/catalogs.py.  That is, we
    use 1.5 times the sigma-clipped standard deviation of the image.  With usemode
    set to True, we instead use the square root of twice the mode.
    """
    from stsci import imagestats
    from numpy import median, sqrt, abs
    if isinstance(filelist, str):
        filelist = [filelist]

    modelist, stddevlist = [], []
    for file in filelist:
        hdulist = pyfits.open(file)

        extnamelist = [ext.name.upper() for ext in hdulist]
        if 'SCI' in extnamelist:
            iextlist = [
                iext for iext in range(len(extnamelist))
                if extnamelist[iext] == 'SCI'
            ]
        else:
            iextlist = [0]
        for iext in iextlist:
            ext = hdulist[iext]
            istats = imagestats.ImageStats(ext.data,
                                           nclip=nclip,
                                           fields='mode,stddev',
                                           binwidth=0.01)
            stddevlist.append(istats.stddev)
            modelist.append(abs(istats.mode))
    if usemode:
        return (sqrt(2.0 * median(modelist)))
    return (1.5 * median(stddevlist))
示例#4
0
 def _compute_sigma(self):
     src_vals = self.source
     if np.any(np.isnan(self.source)):
         src_vals = self.source[np.where(np.isnan(self.source) == False)]
     istats = imagestats.ImageStats(src_vals, nclip=3,
                                    fields='mode,stddev', binwidth=0.01)
     sigma = np.sqrt(2.0 * np.abs(istats.mode))
     return sigma
示例#5
0
#create an empty array for bad pixel mask and donotuse mask
arrshape = (5, 5)
ipc = np.zeros(arrshape)

##Dark images section##
#slopenoiseactive=slopenoise[4:2044,4:2044]
#imstatslope = imagestats.ImageStats(slopenoiseactive,fields="npix,min,max,median,mean,stddev",binwidth=0.1,nclip=3)
#imstatslope.printStats()

#cdsnoiseactive=cdsnoise[4:2044,4:2044]
#imstatcds = imagestats.ImageStats(cdsnoiseactive,fields="npix,min,max,median,mean,stddev",binwidth=0.1,nclip=3)
#imstatcds.printStats()

#darkcurractive=darkcurr[4:2044,4:2044]
imstatdark = imagestats.ImageStats(darkcurr,
                                   fields="npix,min,max,median,mean,stddev",
                                   binwidth=0.1,
                                   nclip=3)
imstatdark.printStats()

#Get hot pixels not in void - need to add void mask sel below
w = (np.where((voidmask != 1) & (hotflagged == 1) & (badflatflagged != 1)
              & (darkcurr > 1.0) & (darkcurr < 100.0)))
print(darkcurr[w].size)
yhotnotvoid = w[0]
xhotnotvoid = w[1]
#print (yhotnotvoid,xhotnotvoid)
numhotnotvoid = yhotnotvoid.size

#Get hot pixels in void - repeat above block
w = (np.where((voidmask == 1) & (hotflagged == 1) & (badflatflagged != 1)
              & (darkcurr > 1.0) & (darkcurr < 100.0)))
示例#6
0
def make_vector_plot(coordfile,columns=[1,2,3,4],data=None,figure_id=None,
                    title=None, axes=None, every=1,labelsize=8, ylimit=None,
                    limit=None, xlower=None, ylower=None, output=None, headl=4,headw=3,
                    xsh=0.0,ysh=0.0,fit=None,scale=1.0,vector=True,textscale=5,
                    append=False,linfit=False,rms=True, plotname=None):
    """ Convert a XYXYMATCH file into a vector plot or set of residuals plots.

        This function provides a single interface for generating either a vector
        plot of residuals or a set of 4 plots showing residuals.  The data being
        plotted can also be adjusted for a linear fit on-the-fly.

        Parameters
        ----------
        coordfile : string
            Name of file with matched sets of coordinates. This input file can
            be a file compatible for use with IRAF's geomap.
        columns : list [Default: [0,1,2,3]]
            Column numbers for the X,Y positions from each image
        data : list of arrays
            If specified, this can be used to input matched data directly
        title : string
            Title to be used for the generated plot
        axes : list
            List of X and Y min/max values to customize the plot axes
        every : int [Default: 1]
            Slice value for the data to be plotted
        limit : float
            Radial offset limit for selecting which sources are included in the plot
        labelsize : int [Default: 8] or str
            Font size to use for tick labels, either in font points or as a string
            understood by tick_params().
        ylimit : float
            Limit to use for Y range of plots.
        xlower : float
        ylower : float
            Limit in X and/or Y offset for selecting which sources are included in the plot
        output : string
            Filename of output file for generated plot
        headl : int [Default: 4]
            Length of arrow head to be used in vector plot
        headw : int [Default: 3]
            Width of arrow head to be used in vector plot
        xsh : float
        ysh : float
            Shift in X and Y from linear fit to be applied to source positions
            from the first image
        scale : float
            Scale from linear fit to be applied to source positions from the
            first image
        fit : array
            Array of linear coefficients for rotation (and scale?) in X and Y from
            a linear fit to be applied to source positions from the first image
        vector : bool [Default: True]
            Specifies whether or not to generate a vector plot. If False, task
            will generate a set of 4 residuals plots instead
        textscale : int [Default: 5]
            Scale factor for text used for labelling the generated plot
        append : bool [Default: False]
            If True, will overplot new plot on any pre-existing plot
        linfit : bool [Default: False]
            If True, a linear fit to the residuals will be generated and
            added to the generated residuals plots
        rms : bool [Default: True]
            Specifies whether or not to report the RMS of the residuals as a
            label on the generated plot(s).
        plotname : str [Default: None]
            Write out plot to a file with this name if specified.

    """
    from matplotlib import pyplot as plt

    if data is None:
        data = readcols(coordfile,cols=columns)

    xy1x = data[0]
    xy1y = data[1]
    xy2x = data[2]
    xy2y = data[3]

    numpts = xy1x.shape[0]
    if fit is not None:
        xy1x,xy1y = apply_db_fit(data,fit,xsh=xsh,ysh=ysh)
        fitstr = '-Fit applied'
        dx = xy2x - xy1x
        dy = xy2y - xy1y
    else:
        dx = xy2x - xy1x - xsh
        dy = xy2y - xy1y - ysh
    # apply scaling factor to deltas
    dx *= scale
    dy *= scale

    print('Total # points: ',len(dx))
    if limit is not None:
        indx = (np.sqrt(dx**2 + dy**2) <= limit)
        dx = dx[indx].copy()
        dy = dy[indx].copy()
        xy1x = xy1x[indx].copy()
        xy1y = xy1y[indx].copy()
    if xlower is not None:
        xindx = (np.abs(dx) >= xlower)
        dx = dx[xindx].copy()
        dy = dy[xindx].copy()
        xy1x = xy1x[xindx].copy()
        xy1y = xy1y[xindx].copy()
    print('# of points after clipping: ',len(dx))

    dr = np.sqrt(dx**2 + dy**2)
    max_vector = dr.max()

    if output is not None:
        write_xy_file(output,[xy1x,xy1y,dx,dy])

    fig = plt.figure(num=figure_id)
    if not append:
        plt.clf()

    if vector:
        dxs = imagestats.ImageStats(dx.astype(np.float32))
        dys = imagestats.ImageStats(dy.astype(np.float32))
        minx = xy1x.min()
        maxx = xy1x.max()
        miny = xy1y.min()
        maxy = xy1y.max()
        xrange = maxx - minx
        yrange = maxy - miny

        qplot = plt.quiver(xy1x[::every],xy1y[::every],dx[::every],dy[::every],\
                  units='y',headwidth=headw,headlength=headl)
        key_dx = xrange*0.01
        key_dy = yrange*(0.005*textscale)
        maxvec = max_vector/2.
        key_len = round((maxvec+0.005),2)

        plt.xlabel('DX: %.4f to %.4f +/- %.4f'%(dxs.min,dxs.max,dxs.stddev))
        plt.ylabel('DY: %.4f to %.4f +/- %.4f'%(dys.min,dys.max,dys.stddev))
        plt.title(r"$Vector\ plot\ of\ %d/%d\ residuals:\ %s$"%(
                xy1x.shape[0],numpts,title))
        plt.quiverkey(qplot,minx+key_dx,miny-key_dy,key_len,"%0.2f pixels"%(key_len),
                    coordinates='data',labelpos='E',labelcolor='Maroon',color='Maroon')
    else:
        plot_defs = [[xy1x,dx,"X (pixels)","DX (pixels)"],\
                    [xy1y,dx,"Y (pixels)","DX (pixels)"],\
                    [xy1x,dy,"X (pixels)","DY (pixels)"],\
                    [xy1y,dy,"Y (pixels)","DY (pixels)"]]
        if axes is None:
            # Compute a global set of axis limits for all plots
            minx = xy1x.min()
            maxx = xy1x.max()
            miny = dx.min()
            maxy = dx.max()

            if xy1y.min() < minx: minx = xy1y.min()
            if xy1y.max() > maxx: maxx = xy1y.max()
            if dy.min() < miny: miny = dy.min()
            if dy.max() > maxy: maxy = dy.max()
        else:
            minx = axes[0][0]
            maxx = axes[0][1]
            miny = axes[1][0]
            maxy = axes[1][1]

        if ylimit is not None:
            miny = -1*ylimit
            maxy = ylimit

        xrange = maxx - minx
        yrange = maxy - miny

        rms_labelled=False
        if title is None:
            fig.suptitle("Residuals [%d/%d]"%(xy1x.shape[0],numpts),ha='center',fontsize=labelsize+6)
        else:
            # This definition of the title supports math symbols in the title
            fig.suptitle(r"$"+title+"$",ha='center', fontsize=labelsize+6)

        for pnum, p in enumerate(plot_defs):
            pn = pnum+1
            ax = fig.add_subplot(2,2,pn)
            plt.plot(p[0],p[1],'b.',label='RMS(X) = %.4f, RMS(Y) = %.4f'%(dx.std(),dy.std()))
            lx=[ int((p[0].min()-500)/500) * 500,int((p[0].max()+500)/500) * 500]
            plt.plot([lx[0],lx[1]],[0.0,0.0],'k',linewidth=3)
            plt.axis([minx,maxx,miny,maxy])
            if rms and not rms_labelled:
                leg_handles, leg_labels = ax.get_legend_handles_labels()
                fig.legend(leg_handles, leg_labels, loc='center left',
                           fontsize='small', frameon=False,
                           bbox_to_anchor=(0.33, 0.51), borderaxespad=0)
                rms_labelled = True

            ax.tick_params(labelsize=labelsize)

            # Fine-tune figure; hide x ticks for top plots and y ticks for right plots
            if pn <= 2:
                plt.setp(ax.get_xticklabels(), visible=False)
            else:
                ax.set_xlabel(plot_defs[pnum][2])

            if pn%2 == 0:
                plt.setp(ax.get_yticklabels(), visible=False)
            else:
                ax.set_ylabel(plot_defs[pnum][3])

            if linfit:
                lxr = int((lx[-1] - lx[0])/100)
                lyr = int((p[1].max() - p[1].min())/100)
                A = np.vstack([p[0],np.ones(len(p[0]))]).T
                m,c = np.linalg.lstsq(A,p[1])[0]
                yr = [m*lx[0]+c,lx[-1]*m+c]
                plt.plot([lx[0],lx[-1]],yr,'r')
                plt.text(lx[0]+lxr,p[1].max()+lyr,"%0.5g*x + %0.5g [%0.5g,%0.5g]"%(m,c,yr[0],yr[1]),color='r')

    plt.draw()

    if plotname:
        suffix = plotname[-4:]
        if '.' not in suffix:
            output += '.png'
            format = 'png'
        else:
            if suffix[1:] in ['png','pdf','ps','eps','svg']:
                format=suffix[1:]
        plt.savefig(plotname,format=format)
meanpcfile = os.path.join(noisedir, outfileroot + 'meandarkzero.fits')
medianpcfile = meanpcfile.replace('meandarkzero', 'mediandarkzero')
stdpcfile = meanpcfile.replace('meandarkzero', 'sigmadarkzero')
fits.writeto(meanpcfile, clippedslope3dpcmean, header, overwrite=True)
fits.writeto(medianpcfile, clippedslope3dpcmedian, header, overwrite=True)
fits.writeto(stdpcfile, clippedslope3dpcstd, header, overwrite=True)

#optionally output stats for dark current and slope noise
if outputstats == True:

    print('PC offsets: ', offsetclippedslope1d)
    print('Std dev of PC offsets: ', np.std(offsetclippedslope1d))

    i = imagestats.ImageStats(clippedslope3dmean[4:2044, 4:2044],
                              fields="npix,min,max,median,mean,stddev",
                              nclip=3,
                              lsig=3.0,
                              usig=3.0,
                              binwidth=0.1)
    print(meanfile)
    i.printStats()
    i = imagestats.ImageStats(clippedslope3dmedian[4:2044, 4:2044],
                              fields="npix,min,max,median,mean,stddev",
                              nclip=3,
                              lsig=3.0,
                              usig=3.0,
                              binwidth=0.1)
    print(medianfile)
    i.printStats()
    i = imagestats.ImageStats(clippedslope3dstd[4:2044, 4:2044],
                              fields="npix,min,max,median,mean,stddev",
                              nclip=3,
示例#8
0
    def _subtract_sky(self, ext_info, flag=-1.0e10):
        """Perform a classical background subtraction."""

        # Derive the name of all aXe products for a given image
        axe_names = config_util.get_axe_names(self.grisim, ext_info)
        msk_image_sc = axe_names['MSK'] + '[SCI]'

        # check for a previous background subtraction
        with fits.open(self.grisim, mode='update') as grism_file:
            if 'AXEPRBCK' in grism_file[ext_info['fits_ext']].header:
                # warn that this is the second time
                _log.info("WARNING: Image %25s seems to be already background "
                          "subtracted!".format(self.grisim))

            # Compute the ratio of the grism SCI image to the background image
            sci_data = grism_file['SCI', ext_info['ext_version']].data
            sci_header = grism_file['SCI', ext_info['ext_version']].header
            npix = int(sci_header["NAXIS1"]) * int(sci_header["NAXIS2"])

            bck_data = fits.getdata(self.master_bck)
            ratio_data = sci_data / bck_data

            # Flag pixels in the ratio image based on the grism image DQ array
            grism_dq_data = grism_file['DQ', ext_info['ext_version']].data
            ratio_data[grism_dq_data > 0.5] = flag

            # Flag pixels in the ratio image based on the grism image MSK file
            msk_file = fits.open(
                config_util.getOUTPUT(msk_image_sc.split("[")[0]), 'readonly')
            msk_data = msk_file['SCI'].data
            msk_file.close()

            ratio_data[msk_data < -900000] = flag

            # Flag pixels in the background image based on the grism image DQ
            # and MSK file
            bck_data[grism_dq_data > 0.5] = flag
            bck_data[msk_data < -900000] = flag

            # Compute stats for the ratio image
            stats = imagestats.ImageStats(ratio_data[ratio_data > flag],
                                          fields='midpt,stddev,npix',
                                          lower=None,
                                          upper=None,
                                          nclip=3,
                                          lsig=3.0,
                                          usig=3.0,
                                          binwidth=0.01)

            # Compute stats for the background image
            bstats = imagestats.ImageStats(bck_data[bck_data > flag],
                                           fields='midpt,stddev,npix',
                                           lower=None,
                                           upper=None,
                                           nclip=3,
                                           lsig=3.0,
                                           usig=3.0,
                                           binwidth=0.01)

            # Subtract the scaled background from the grism image
            # Reload a clean version of background
            bck_data = fits.getdata(self.master_bck)

            grism_file['SCI',
                       ext_info['ext_version']].data -= bck_data * stats.midpt
            grism_header = grism_file['SCI', ext_info['ext_version']].header

            # write some header iformation
            grism_header['SKY_SCAL'] = (float(
                stats.midpt), 'scaling value for the master background')
            grism_header['SKY_MAST'] = (float(
                bstats.midpt), 'average value of the master background')
            grism_header['SKY_IMG'] = (self.master_bck,
                                       'name of the master background image')
            grism_header['F_SKYPIX'] = (float(stats.npix) / float(npix),
                                        'fraction of pixels used for scaling')
            grism_header['AXEPRBCK'] = (
                'Done', 'flag that background subtraction was done')
        return 0
    def _subtract_sky(self, ext_info):
        """
        Make a classical background subtraction
        """
        import os, shutil

        from pyraf import iraf
        from iraf import stsdas

        from astropy.io import fits as pyfits
        import stsci.imagestats as imagestats

        # get the axe names
        axe_names = axeutils.get_axe_names(self.grisim, ext_info)

        msk_image_sc = axe_names['MSK'] + '[SCI]'

        # check for a previous background subtraction
        fits_img = pyfits.open(axeutils.getIMAGE(self.grisim), 'readonly')
        fits_head = fits_img[ext_info['fits_ext']].header
        npix = int(fits_head['NAXIS1']) * int(fits_head['NAXIS1'])

        if 'AXEPRBCK' in fits_head:
            # warn that this is the second time
            print(
                'WARNING: Image %25s seems to be already background subtracted!'
                % axeutils.getIMAGE(self.grisim))

        # close the fits
        fits_img.close()

        # Compute the ratio of the grism SCI image to the background image
        sci_file = pyfits.open(axeutils.getIMAGE(self.grisim), 'readonly')
        sci_data = sci_file['SCI', ext_info['ext_version']].data
        bck_file = pyfits.open(axeutils.getCONF(self.master_bck), 'readonly')
        bck_data = bck_file[0].data
        sci_data /= bck_data

        # Flag pixels in the ratio image based on the grism image DQ array
        dq_data = sci_file['DQ', ext_info['ext_version']].data
        sci_data[dq_data > 0.5] = -1.0e10

        # Flag pixels in the ratio image based on the grism image MSK file
        msk_file = pyfits.open(axeutils.getOUTPUT(msk_image_sc.split("[")[0]),
                               'readonly')
        msk_data = msk_file['SCI'].data
        sci_data[msk_data < -900000] = -1.0e10

        # Flag pixels in the background image based on the grism image DQ
        # and MSK file
        bck_data[dq_data > 0.5] = -1.0e10
        bck_data[msk_data < -900000] = -1.0e10

        # Compute stats for the ratio image
        stats = imagestats.ImageStats(sci_data[sci_data > -1.0e9],
                                      fields='midpt,stddev,npix',
                                      lower=None,
                                      upper=None,
                                      nclip=3,
                                      lsig=3.0,
                                      usig=3.0,
                                      binwidth=0.01)
        flt_ave = stats.midpt
        flt_std = stats.stddev
        flt_npx = stats.npix
        frac_pix = float(flt_npx) / float(npix)

        # Compute stats for the background image
        stats = imagestats.ImageStats(bck_data[bck_data > -1.0e9],
                                      fields='midpt,stddev,npix',
                                      lower=None,
                                      upper=None,
                                      nclip=3,
                                      lsig=3.0,
                                      usig=3.0,
                                      binwidth=0.01)
        mst_ave = stats.midpt
        mst_std = stats.stddev
        mst_npx = stats.npix

        sci_file.close()
        bck_file.close()
        msk_file.close()

        # Subtract the scaled background from the grism image
        sci_file = pyfits.open(axeutils.getIMAGE(self.grisim), 'update')
        bck_file = pyfits.open(axeutils.getCONF(self.master_bck), 'readonly')
        sci_file['SCI',
                 ext_info['ext_version']].data -= flt_ave * bck_file[0].data
        sci_file.close()
        bck_file.close()

        # open the fits image ands isolate the correct extension
        grism_img = pyfits.open(axeutils.getIMAGE(self.grisim), 'update')
        grism_header = grism_img[ext_info['fits_ext']].header

        # write some header iformation
        grism_header['SKY_SCAL'] = (float(flt_ave),
                                    'scaling value for the master background')
        grism_header['SKY_MAST'] = (float(mst_ave),
                                    'average value of the master background')
        grism_header['SKY_IMG'] = (self.master_bck,
                                   'name of the master background image')
        grism_header['F_SKYPIX'] = (frac_pix,
                                    'fraction of pixels used for scaling')
        grism_header['AXEPRBCK'] = (
            'Done', 'flag that background subtraction was done')

        # save the image
        grism_img.close()

        return 0
示例#10
0
print(lines1, lines2)

positions = []
shift = []
for k in np.ndenumerate(lines2):
    #get both indicies for the two cubes being aligned
    j = int(lines1[k[0]])
    i = int(k[-1])

    #more sanity checks
    print(i)
    print(j)

    #sum over the spectral range of each line to first get image of the entire nebular line
    #Then find the mean pixel value of each resulting image
    mean1 = imagestats.ImageStats(np.sum(data1[j - 5:j + 5, :, :], axis=0),
                                  nclip=0).mean
    mean2 = imagestats.ImageStats(np.sum(data2[i - 5:i + 5, :, :], axis=0),
                                  nclip=0).mean
    #subtract the mean from the image
    image1 = np.sum(data1[j - 5:j + 5, :, :], axis=0) - mean1
    image2 = np.sum(data2[i - 5:i + 5, :, :], axis=0) - mean2

    #Now subsample each pixel to 5x5 subpixels to better increase accuracy of alignment.
    scalefactor = 5.
    image1 = ndimage.zoom(image1, scalefactor, order=3)
    image2 = ndimage.zoom(image2, scalefactor, order=3)

    #Correlate the subsampled images to find where they line up best
    corr = ndimage.correlate(image1, image2, mode='constant')
    corrout = fits.PrimaryHDU(corr)
    corrout.writeto("corr" + str(i) + ".fits", overwrite=True)