Ejemplo n.º 1
0
def aperphot(fn, timekey=None, pos=[0,0], dap=[2,4,6], mask=None, verbose=False, nanval=999, resamp=None, retfull=False, ignorenan=True):
    """Do aperture photometry on a specified file.

    :INPUTS:
      pos : 2-sequence
        center of apertures (as if indexing: fn[pos[0], pos[1]])
  
      dap : 3-sequence
        Photometry aperture DIAMETERS:
           -- target aperture (within which to sum flux)
           -- inner sky aperture
           -- outer sky aperture
  
      resamp : int
        Factor by which to interpolate frame before measuring photometry
        (in essence, does partial-pixel aperture photometry)
  
      Aperture masking:
         If no mask is passed in, use the star's input position and
         aperture diameters to create binary pixel masks for stellar and
         background photometry.  If a mask is passed in, stellar and
         background aperture masks are generated from where all input
         mask elements equal 1 and 2, respectively.
  
      retfull: 
          Also return arrays of target mask, sky mask, and frame used.
          This option is a memory hog!
  
    :OUTPUTS:  
      :class:`phot` object.  
  
    :EXAMPLE:  
      ::

        import astropy.io.fits
        from astropy import wcs
        import numpy as np
        from phot import aperphot

        img='62_z_CDFs_goods_stamp_img.fits'  #path to the image
        RA = 52.9898239
        DEC = -27.7143114
        hdulist = astropy.io.fits.open(img)
        w = wcs.WCS(hdulist['PRIMARY'].header)
        world = np.array([[RA, DEC]])
        pix = w.wcs_world2pix(world,1) # Pixel coordinates of (RA, DEC)
        print "Pixel Coordinates: ", pix[0,0], pix[0,1]

        #call aperture function
        observation=aperphot(img, timekey=None, pos=[pix[0,0], pix[0,1]], dap=[4,8,12], resamp=2, retfull=False)

        # Print outputs
        print "Aperture flux:", observation.phot
        print "Background:   ", observation.bg
  
  
    :REQUIREMENTS:
      scipy.interpolate, pyfits, numpy...
           """
    # 2009-09-14 10:49 IJC: Created
    # 2010-01-15 14:20 IJC: Added numpy "_string" check
    # 2011-12-29 12:01 IJMC: Added peak pixel values to photometry report.
    # 2012-01-25 11:26 IJMC: Adding "resamp" option -- thanks to
    #                        K. Stevenson and J. Harrington of UCF for
    #                        the suggestion.
    # 2012-02-26 11:53 IJMC: Now return 'ntarg' and 'nsky' -- number of pixels used.
    # 2012-06-07 08:27 IJMC: 'peak' values are now corrected for the
    #                        resampling factor.
    # 2012-07-03 10:35 IJMC: Fixed a key bug: frames were not
    #                        correctly background-subtracted when
    #                        applying partial-pixel resampling.
    # 2012-10-19 13:41 IJMC: Documented 'retfull' option; changed default.
    # 2013-03-20 09:21 IJMC: More error-checking for saving header
    #                        keywords.  Thanks to A. Weigel @
    #                        ETH-Zurich for catching this!
    # 2014-05-07 16:05: added "ephot" by J. Xavier Prochaska, UCSC
    # 2014-08-28 09:32 IJMC: Added better checking for user-input
    #                        masks and resamp>1. Corrected x/y
    #                        indexing for non-square inputs arrays.
    # 2014-09-06 14:41 IJMC: Added better checking for dap & pos.
    # 2014-09-08 10:10 IJMC: Fix masking & nan-handling.

    from numpy import meshgrid, median,isfinite,sort,ndarray,string_
    import numpy as np

    try:
        from astropy.io import fits as pyfits
    except:
        import pyfits
    
    from analysis import fixval
    from os import path
    from scipy import interpolate

    thisobs = phot()
    if pos is None:
        pos = 0, 0
    if dap is None:
        dap = 1, 2, 3

    x0, y0 = pos
    dap_targ, dap_skyinner, dap_skyouter = dap
    if resamp is None or resamp<1:
        resamp = 1
    else:
        resamp = float(resamp)
        
    # Determine size:
    if isinstance(fn,str):
        nx = pyfits.getval(fn, 'NAXIS2')
        ny = pyfits.getval(fn, 'NAXIS1')
    elif isinstance(fn,ndarray):
        nx,ny = fn.shape

    nx0, ny0 = nx, ny
    nx = ((nx - 1)*resamp + 1.)  # Avoid resampling at pixel locations
    ny = ((ny - 1)*resamp + 1.)  #   outside the original boundaries.

    # Generate or load masks:
    if mask is None:
        xx,yy = meshgrid(np.arange(ny)/resamp, np.arange(nx)/resamp)
        mask_targ = makemask(xx, yy, (y0, x0, dap_targ))
        mask_s1 = makemask(xx, yy, (y0,x0, dap_skyinner))
        mask_s2 = makemask(xx, yy, (y0,x0, dap_skyouter))
        mask_sky = mask_s2 - mask_s1
        userInputMask = False
        #pdb.set_trace()
    else:
        mask_targ = mask==1
        mask_sky = mask==2
        userInputMask = True


    # Load data frame:
    thisobs = phot()
    if pos is None:
        pos = 0, 0
    if dap is None:
        dap = 1, 2, 3

    if isinstance(fn,ndarray):
        frame = fn
    elif isinstance(fn, str) or isinstance(fn,string_):
        if not path.isfile(fn):
            print "file %s not found! exiting..." % fn
            return thisobs
        frame = pyfits.getdata(fn)
        fixval(frame, nanval)

    # Resample data frame
    badval = -12345.6789
    if resamp>1:
        frame0 = frame.copy()
        mask_good0 = np.isfinite(frame0)
        frame0[True-mask_good0] = badval
        xx0 = range(nx0)
        yy0 = range(ny0)
        x1,y1 = np.arange(nx)/resamp, np.arange(ny)/resamp
        rectspline = interpolate.fitpack2.RectBivariateSpline(xx0, yy0, frame0, kx=1, ky=1, s=0)
        frame = rectspline(x1, y1)
        if userInputMask and \
              ((frame.shape<>mask_targ.shape) or (frame.shape<>mask_sky.shape)):
            print "User-entered mask did not have the correct size for the resampling"
            print "  input used (resamp=%1.3f). Beware!" % resamp
            stop

    if ignorenan:
        mask_good = np.isfinite(frame)
        mask_targ = mask_targ * mask_good
        mask_sky  = mask_sky * mask_good

    #from pylab import *
    #pdb.set_trace()
    # Measure background and aperture photometry
    thisbg, thisebg = estbg(frame, mask=mask_sky, plotalot=verbose, rout=[3,99], verbose=verbose)
    if not np.isfinite(thisbg):
        thisbg = 0.
    thisphot = ((frame - thisbg)[mask_targ]).sum() /resamp/resamp
    peak = frame.max()
    peak_targ = frame[mask_targ].max()
    peak_annulus = frame[mask_sky].max()

    thisobs.bg=thisbg
    thisobs.ebg=thisebg
    thisobs.bgstr='phot.estbg: SDOM on bg histogram mean & dispersion after outlier rejection'
    thisobs.phot=thisphot
    thisobs.photstr='by-hand background-subtracted aperture photometry'
    thisobs.ntarg = mask_targ.sum()/resamp/resamp
    thisobs.nsky = mask_sky.sum()/resamp/resamp

    thisobs.peak = peak
    thisobs.peak_targ = peak_targ
    thisobs.peak_annulus = peak_annulus
    thisobs.peakstr = 'peak pixel value in frame'
    thisobs.peak_targstr = 'peak pixel value in target aperture'
    thisobs.peak_annulusstr = 'peak pixel value in sky annulus'
    thisobs.position = pos
    thisobs.positionstr = 'user-specified, zero-indexed pixel coordinates.'
    if isinstance(fn, str):
        header = pyfits.getheader(fn)
        if not timekey is None:
            if timekey in header: 
                thisobs.time=header['timekey']
                thisobs.timestr='heliocentric modified julian date'
        if 'object' in header:  thisobs.object = header['object']
        if 'exptime' in header: thisobs.exptime = header['exptime']
    thisobs.aper = dap
    thisobs.aperstr = 'target, inner, outer aperture diameters, in pixels.'
    thisobs.filename=fn
    thisobs.resamp = resamp

    # Simple stats :: JXP 2014 May 6
    var = thisphot + np.sqrt(thisobs.nsky)*thisobs.bg 
    thisobs.ephot = np.sqrt(var)


    if retfull:
        thisobs.mask_targ = mask_targ
        thisobs.mask_sky  = mask_sky
        thisobs.frame = frame

    if verbose>0:
        from pylab import figure, colorbar
        from nsdata import imshow
        figure(); imshow(frame*mask_targ); colorbar()
        figure(); imshow(frame*mask_sky); colorbar()

    return thisobs
Ejemplo n.º 2
0
def aperphot(fn, timekey=None, pos=[0,0], dap=[2,4,6], mask=None, verbose=False, nanval=999, resamp=None, retfull=False, ignorenan=True):
    """Do aperture photometry on a specified file.

    :INPUTS:
      pos : 2-sequence
        center of apertures (as if indexing: fn[pos[0], pos[1]])
  
      dap : 3-sequence
        Photometry aperture DIAMETERS:
           -- target aperture (within which to sum flux)
           -- inner sky aperture
           -- outer sky aperture
  
      resamp : int
        Factor by which to interpolate frame before measuring photometry
        (in essence, does partial-pixel aperture photometry)
  
      Aperture masking:
         If no mask is passed in, use the star's input position and
         aperture diameters to create binary pixel masks for stellar and
         background photometry.  If a mask is passed in, stellar and
         background aperture masks are generated from where all input
         mask elements equal 1 and 2, respectively.
  
      retfull: 
          Also return arrays of target mask, sky mask, and frame used.
          This option is a memory hog!
  
    :OUTPUTS:  
      :class:`phot` object.  
  
    :EXAMPLE:  
      ::

        import astropy.io.fits
        from astropy import wcs
        import numpy as np
        from phot import aperphot

        img='62_z_CDFs_goods_stamp_img.fits'  #path to the image
        RA = 52.9898239
        DEC = -27.7143114
        hdulist = astropy.io.fits.open(img)
        w = wcs.WCS(hdulist['PRIMARY'].header)
        world = np.array([[RA, DEC]])
        pix = w.wcs_world2pix(world,1) # Pixel coordinates of (RA, DEC)
        print "Pixel Coordinates: ", pix[0,0], pix[0,1]

        #call aperture function
        observation=aperphot(img, timekey=None, pos=[pix[0,0], pix[0,1]], dap=[4,8,12], resamp=2, retfull=False)

        # Print outputs
        print "Aperture flux:", observation.phot
        print "Background:   ", observation.bg
  
  
    :REQUIREMENTS:
      scipy.interpolate, pyfits, numpy...
           """
    # 2009-09-14 10:49 IJC: Created
    # 2010-01-15 14:20 IJC: Added numpy "_string" check
    # 2011-12-29 12:01 IJMC: Added peak pixel values to photometry report.
    # 2012-01-25 11:26 IJMC: Adding "resamp" option -- thanks to
    #                        K. Stevenson and J. Harrington of UCF for
    #                        the suggestion.
    # 2012-02-26 11:53 IJMC: Now return 'ntarg' and 'nsky' -- number of pixels used.
    # 2012-06-07 08:27 IJMC: 'peak' values are now corrected for the
    #                        resampling factor.
    # 2012-07-03 10:35 IJMC: Fixed a key bug: frames were not
    #                        correctly background-subtracted when
    #                        applying partial-pixel resampling.
    # 2012-10-19 13:41 IJMC: Documented 'retfull' option; changed default.
    # 2013-03-20 09:21 IJMC: More error-checking for saving header
    #                        keywords.  Thanks to A. Weigel @
    #                        ETH-Zurich for catching this!
    # 2014-05-07 16:05: added "ephot" by J. Xavier Prochaska, UCSC
    # 2014-08-28 09:32 IJMC: Added better checking for user-input
    #                        masks and resamp>1. Corrected x/y
    #                        indexing for non-square inputs arrays.
    # 2014-09-06 14:41 IJMC: Added better checking for dap & pos.
    # 2014-09-08 10:10 IJMC: Fix masking & nan-handling.

    from numpy import meshgrid, median,isfinite,sort,ndarray,string_
    import numpy as np

    try:
        from astropy.io import fits as pyfits
    except:
        import pyfits
    
    from analysis import fixval
    from os import path
    from scipy import interpolate

    thisobs = phot()
    if pos is None:
        pos = 0, 0
    if dap is None:
        dap = 1, 2, 3

    x0, y0 = pos
    dap_targ, dap_skyinner, dap_skyouter = dap
    if resamp is None or resamp<1:
        resamp = 1
    else:
        resamp = float(resamp)
        
    # Determine size:
    if isinstance(fn,str):
        nx = pyfits.getval(fn, 'NAXIS2')
        ny = pyfits.getval(fn, 'NAXIS1')
    elif isinstance(fn,ndarray):
        nx,ny = fn.shape

    nx0, ny0 = nx, ny
    nx = ((nx - 1)*resamp + 1.)  # Avoid resampling at pixel locations
    ny = ((ny - 1)*resamp + 1.)  #   outside the original boundaries.

    # Generate or load masks:
    if mask==None:
        xx,yy = meshgrid(np.arange(ny)/resamp, np.arange(nx)/resamp)
        mask_targ = makemask(xx, yy, (y0, x0, dap_targ))
        mask_s1 = makemask(xx, yy, (y0,x0, dap_skyinner))
        mask_s2 = makemask(xx, yy, (y0,x0, dap_skyouter))
        mask_sky = mask_s2 - mask_s1
        userInputMask = False
        #pdb.set_trace()
    else:
        mask_targ = mask==1
        mask_sky = mask==2
        userInputMask = True


    # Load data frame:
    thisobs = phot()
    if pos is None:
        pos = 0, 0
    if dap is None:
        dap = 1, 2, 3

    if isinstance(fn,ndarray):
        frame = fn
    elif isinstance(fn, str) or isinstance(fn,string_):
        if not path.isfile(fn):
            print "file %s not found! exiting..." % fn
            return thisobs
        frame = pyfits.getdata(fn)
        fixval(frame, nanval)

    # Resample data frame
    badval = -12345.6789
    if resamp>1:
        frame0 = frame.copy()
        mask_good0 = np.isfinite(frame0)
        frame0[True-mask_good0] = badval
        xx0 = range(nx0)
        yy0 = range(ny0)
        x1,y1 = np.arange(nx)/resamp, np.arange(ny)/resamp
        rectspline = interpolate.fitpack2.RectBivariateSpline(xx0, yy0, frame0, kx=1, ky=1, s=0)
        frame = rectspline(x1, y1)
        if userInputMask and \
              ((frame.shape<>mask_targ.shape) or (frame.shape<>mask_sky.shape)):
            print "User-entered mask did not have the correct size for the resampling"
            print "  input used (resamp=%1.3f). Beware!" % resamp
            stop

    if ignorenan:
        mask_good = np.isfinite(frame)
        mask_targ = mask_targ * mask_good
        mask_sky  = mask_sky * mask_good

    #from pylab import *
    #pdb.set_trace()
    # Measure background and aperture photometry
    thisbg, thisebg = estbg(frame, mask=mask_sky, plotalot=verbose, rout=[3,99], verbose=verbose)
    if not np.isfinite(thisbg):
        thisbg = 0.
    thisphot = ((frame - thisbg)[mask_targ]).sum() /resamp/resamp
    peak = frame.max()
    peak_targ = frame[mask_targ].max()
    peak_annulus = frame[mask_sky].max()

    thisobs.bg=thisbg
    thisobs.ebg=thisebg
    thisobs.bgstr='phot.estbg: SDOM on bg histogram mean & dispersion after outlier rejection'
    thisobs.phot=thisphot
    thisobs.photstr='by-hand background-subtracted aperture photometry'
    thisobs.ntarg = mask_targ.sum()/resamp/resamp
    thisobs.nsky = mask_sky.sum()/resamp/resamp

    thisobs.peak = peak
    thisobs.peak_targ = peak_targ
    thisobs.peak_annulus = peak_annulus
    thisobs.peakstr = 'peak pixel value in frame'
    thisobs.peak_targstr = 'peak pixel value in target aperture'
    thisobs.peak_annulusstr = 'peak pixel value in sky annulus'
    thisobs.position = pos
    thisobs.positionstr = 'user-specified, zero-indexed pixel coordinates.'
    if isinstance(fn, str):
        header = pyfits.getheader(fn)
        if not timekey==None:
            if timekey in header: 
                thisobs.time=header['timekey']
                thisobs.timestr='heliocentric modified julian date'
        if 'object' in header:  thisobs.object = header['object']
        if 'exptime' in header: thisobs.exptime = header['exptime']
    thisobs.aper = dap
    thisobs.aperstr = 'target, inner, outer aperture diameters, in pixels.'
    thisobs.filename=fn
    thisobs.resamp = resamp

    # Simple stats :: JXP 2014 May 6
    var = thisphot + np.sqrt(thisobs.nsky)*thisobs.bg 
    thisobs.ephot = np.sqrt(var)


    if retfull:
        thisobs.mask_targ = mask_targ
        thisobs.mask_sky  = mask_sky
        thisobs.frame = frame

    if verbose>0:
        from pylab import figure, colorbar
        from nsdata import imshow
        figure(); imshow(frame*mask_targ); colorbar()
        figure(); imshow(frame*mask_sky); colorbar()

    return thisobs
Ejemplo n.º 3
0
def estbg(im, mask=None, bins=None, plotalot=False, rout=(3,200), badval=nan, verbose=False):
    """Estimate the background value of a masked image via histogram fitting.

    INPUTS:
      im -- numpy array.  Input image.

    OPTIONAL INPUTS:
      mask -- numpy array. logical mask, False/0 in regions to ignore
      bins -- sequence.  edges of bins to pass to HIST
      plotalot -- bool.  Plot the histogram and fit.
      rout -- 2-tuple of (nsigma, niter) for analysis.removeoutliers.
              Set to (Inf, 0) to not cut any outliers.
      badval -- value returned when things go wrong.

    OUTPUT:
      b, s_b -- tuple of (background, error on background) from gaussian fit.
                 Note that the error is analagous to the standard deviation on the mean

    COMMENTS:
      The fit parameters appear to be robust across a fairly wide range of bin sizes.  """
    # 2009-09-02 17:13 IJC: Created!
    # 2009-09-04 15:07 IJC: Added RemoveOutliers option. Use only non-empty bins in fit.
    # 2009-09-08 15:32 IJC: Error returned is now divided by sqrt(N) for SDOM
    # 2009-11-03 00:16 IJC: Improved guess for gaussian dispersion
    # 2011-05-18 11:47 IJMC: Moved (e)gaussian imports to analysis.
    # 2012-01-01 21:04 IJMC: Added badval option
    # 2012-08-15 17:45 IJMC: Numpy's new histogram no longer accepts 'new' keyword
    # 2013-03-20 08:22 IJMC: Now works better even for small numbers
    #                        of pixels; thanks to A. Weigel @
    #                        ETH-Zurich for catching this!
    # 2014-08-29 10:05 IJMC: Added verbosity flag.
    # 2014-09-25 14:29 IJMC: Added check for no usability

    from numpy import histogram, mean, median, sqrt, linspace, isfinite, ones,std
    from pylab import find
    from scipy import optimize
    from analysis import removeoutliers, egaussian, gaussian, stdr
    if plotalot:
        from pylab import figure, errorbar, plot, colorbar, title, hist, mean, std
        #from analysis import imshow

    def gaussianChiSquared(guess, x, y, err):
        return (egaussian(guess, x, y, e=err)**2).sum()


    if mask is None:
        mask = ones(im.shape)
    dat = im.ravel()[find(mask<>0)]
    if plotalot:
        figure(); plot(im.ravel()); plot(dat)
        print mean(dat), std(dat), rout[0]*std(dat)
        print len(dat), (abs(dat-mean(dat))<(rout[0]*std(dat))).sum()
        figure(); plot(dat-mean(dat)); 
        plot([0,len(dat)], [rout[0]*std(dat),rout[0]*std(dat)],'--k')
        plot([0,len(dat)], [-rout[0]*std(dat),-rout[0]*std(dat)],'--k')
    dat = removeoutliers(dat, rout[0], remove='both', center='mean', niter=rout[1], verbose=plotalot)
    ndat = len(dat)

    if ndat==0:
        if verbose>0:   print "No data to work with!"
        return (badval, badval)
    if bins is None:
        if plotalot or verbose: print "no bins entered!"
        datmean = dat.mean()
        datstd = stdr(dat, nsigma=3)
        nunique = len(np.unique(dat.ravel()))
        #pdb.set_trace()
        if nunique > len(dat)/20.:
            dobin = False
        elif nunique>1:
            dobin = True
            bins = linspace(dat.min(), dat.max(), nunique/2)
        else:
            dobin = True
            bins = np.array([dat[0]-1, dat[0]+1])

    if plotalot or verbose: 
        print "dat.mean, dat.std>>" + str((dat.mean(), dat.std()))


    #if plotalot:
    #    figure(); hout = hist(dat[datIndex],bins)
    #else:
    
    if dobin:
        binwidth = mean(bins[1::]-bins[:-1])
        bincenter = 0.5*(bins[1::]+bins[:-1])
        datIndex = (dat>=bins.min()) * (dat<=bins.max())
        hout = histogram(dat[datIndex], bins) #,new=True)
        gy = hout[0]
        erry = sqrt(gy)
        usableIndex = gy>0

        if usableIndex.size==0:
            return badval, badval

        eff_binwidth = mean(bins[usableIndex][1::]-bins[usableIndex][:-1])
        guess = [gy.sum()*eff_binwidth, std(dat[datIndex]), median(dat[datIndex])]

        if 1.0*usableIndex.sum()/usableIndex.size < 0.5:
            out = guess
        else:
            out = optimize.fmin(gaussianChiSquared, guess, \
                                args=(bincenter[usableIndex],gy[usableIndex], erry[usableIndex]), \
                                disp=plotalot)

        if plotalot:
            from pylab import figure, errorbar, plot, colorbar, title
            from nsdata import imshow
            print 'guess>>',guess
            print 'fit>>',out
            figure()
            imshow(im); colorbar()
            figure()
            errorbar(bincenter[usableIndex], gy[usableIndex], erry[usableIndex], fmt='ob')
            plot(bincenter, gaussian(out, bincenter),'-r', linewidth=2)
            title('Mean: %f, Std. Dev.: %f' % (out[2], out[1]))

        ret = out[2], out[1]/sqrt(ndat)
    else:
        ret = datmean, datstd/sqrt(ndat)

    return  ret
Ejemplo n.º 4
0
def estbg(im, mask=None, bins=None, plotalot=False, rout=(3,200), badval=nan, verbose=False):
    """Estimate the background value of a masked image via histogram fitting.

    INPUTS:
      im -- numpy array.  Input image.

    OPTIONAL INPUTS:
      mask -- numpy array. logical mask, False/0 in regions to ignore
      bins -- sequence.  edges of bins to pass to HIST
      plotalot -- bool.  Plot the histogram and fit.
      rout -- 2-tuple of (nsigma, niter) for analysis.removeoutliers.
              Set to (Inf, 0) to not cut any outliers.
      badval -- value returned when things go wrong.

    OUTPUT:
      b, s_b -- tuple of (background, error on background) from gaussian fit.
                 Note that the error is analagous to the standard deviation on the mean

    COMMENTS:
      The fit parameters appear to be robust across a fairly wide range of bin sizes.  """
    # 2009-09-02 17:13 IJC: Created!
    # 2009-09-04 15:07 IJC: Added RemoveOutliers option. Use only non-empty bins in fit.
    # 2009-09-08 15:32 IJC: Error returned is now divided by sqrt(N) for SDOM
    # 2009-11-03 00:16 IJC: Improved guess for gaussian dispersion
    # 2011-05-18 11:47 IJMC: Moved (e)gaussian imports to analysis.
    # 2012-01-01 21:04 IJMC: Added badval option
    # 2012-08-15 17:45 IJMC: Numpy's new histogram no longer accepts 'new' keyword
    # 2013-03-20 08:22 IJMC: Now works better even for small numbers
    #                        of pixels; thanks to A. Weigel @
    #                        ETH-Zurich for catching this!
    # 2014-08-29 10:05 IJMC: Added verbosity flag.
    # 2014-09-25 14:29 IJMC: Added check for no usability

    from numpy import histogram, mean, median, sqrt, linspace, isfinite, ones,std
    from pylab import find
    from scipy import optimize
    from analysis import removeoutliers, egaussian, gaussian, stdr
    if plotalot:
        from pylab import figure, errorbar, plot, colorbar, title, hist, mean, std
        #from analysis import imshow

    def gaussianChiSquared(guess, x, y, err):
        return (egaussian(guess, x, y, e=err)**2).sum()


    if mask==None:
        mask = ones(im.shape)
    dat = im.ravel()[find(mask<>0)]
    if plotalot:
        figure(); plot(im.ravel()); plot(dat)
        print mean(dat), std(dat), rout[0]*std(dat)
        print len(dat), (abs(dat-mean(dat))<(rout[0]*std(dat))).sum()
        figure(); plot(dat-mean(dat)); 
        plot([0,len(dat)], [rout[0]*std(dat),rout[0]*std(dat)],'--k')
        plot([0,len(dat)], [-rout[0]*std(dat),-rout[0]*std(dat)],'--k')
    dat = removeoutliers(dat, rout[0], remove='both', center='mean', niter=rout[1], verbose=plotalot)
    ndat = len(dat)

    if ndat==0:
        if verbose>0:   print "No data to work with!"
        return (badval, badval)
    if bins==None:
        if plotalot or verbose: print "no bins entered!"
        datmean = dat.mean()
        datstd = stdr(dat, nsigma=3)
        nunique = len(np.unique(dat.ravel()))
        #pdb.set_trace()
        if nunique > len(dat)/20.:
            dobin = False
        elif nunique>1:
            dobin = True
            bins = linspace(dat.min(), dat.max(), nunique/2)
        else:
            dobin = True
            bins = np.array([dat[0]-1, dat[0]+1])

    if plotalot or verbose: 
        print "dat.mean, dat.std>>" + str((dat.mean(), dat.std()))


    #if plotalot:
    #    figure(); hout = hist(dat[datIndex],bins)
    #else:
    
    if dobin:
        binwidth = mean(bins[1::]-bins[:-1])
        bincenter = 0.5*(bins[1::]+bins[:-1])
        datIndex = (dat>=bins.min()) * (dat<=bins.max())
        hout = histogram(dat[datIndex], bins) #,new=True)
        gy = hout[0]
        erry = sqrt(gy)
        usableIndex = gy>0

        if usableIndex.size==0:
            return badval, badval

        eff_binwidth = mean(bins[usableIndex][1::]-bins[usableIndex][:-1])
        guess = [gy.sum()*eff_binwidth, std(dat[datIndex]), median(dat[datIndex])]

        if 1.0*usableIndex.sum()/usableIndex.size < 0.5:
            out = guess
        else:
            out = optimize.fmin(gaussianChiSquared, guess, \
                                args=(bincenter[usableIndex],gy[usableIndex], erry[usableIndex]), \
                                disp=plotalot)

        if plotalot:
            from pylab import figure, errorbar, plot, colorbar, title
            from nsdata import imshow
            print 'guess>>',guess
            print 'fit>>',out
            figure()
            imshow(im); colorbar()
            figure()
            errorbar(bincenter[usableIndex], gy[usableIndex], erry[usableIndex], fmt='ob')
            plot(bincenter, gaussian(out, bincenter),'-r', linewidth=2)
            title('Mean: %f, Std. Dev.: %f' % (out[2], out[1]))

        ret = out[2], out[1]/sqrt(ndat)
    else:
        ret = datmean, datstd/sqrt(ndat)

    return  ret