Created
October 25, 2011 00:29
-
-
Save jiffyclub/1310937 to your computer and use it in GitHub Desktop.
Find modal sky on an array.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy, pylab, scipy | |
from scipy import optimize | |
# Uses MEANCLIP from above | |
from meanclip import meanclip | |
def msky(inarray, do_plot=0, verbose=0, ptitle='', func=0): | |
""" | |
Find modal sky on an array. | |
First step is determination of median value and sigma. | |
Histogram of the data and fit parabola to the | |
logaritmic histogram. The coefficient of the parabola | |
are used to get mode and sigma of the sky on the | |
assumption that it is well fitted by a gaussian or | |
2nd-degree polynomial. | |
.. note:: MYSKY5 routine from ACS library. | |
:History: | |
* 11/25/2009 Created by PLL based on IDL routine by MS. | |
* 01/29/2010 PLL fixed broken where statement for histogram. | |
Parameters | |
---------- | |
inarray: array_like | |
Input data. | |
do_plot: {0, 1} | |
Do plot? | |
verbose: {0, 1} | |
Print info to screen? | |
ptitle: string | |
Title of plot. Only used if `do_plot`=1. | |
func: {0, 1} | |
Function for fitting: | |
* 0: 2nd degree polynomial | |
* 1: Gaussian | |
Returns | |
------- | |
mmean: float | |
Mode of fitted function. | |
sigma: float | |
Sigma of fitted function. | |
""" | |
# Constants | |
func_name = 'MSKY' | |
nsig = 8.0 | |
c1 = 2.5 # 2.8 | |
c2 = 0.8 # 1.3 | |
# Min/max of input array | |
arr_min = numpy.min(inarray) | |
arr_max = numpy.max(inarray) | |
# Get sigma | |
mmean, sigma = meanclip(inarray, clipsig=5.0, maxiter=10, verbose=verbose) | |
if sigma <= 0: | |
print ' ' | |
print '%s: Weird distribution' % func_name | |
print '%-6s: %.6f' % ('MEAN', mmean) | |
print '%-6s: %.6f' % ('STDDEV', sigma) | |
print '%-6s: %.6f' % ('MIN', arr_min) | |
print '%-6s: %.6f' % ('MAX', arr_max) | |
return mmean, sigma | |
# Print info | |
if verbose: | |
print ' ' | |
print '%s input array info' % func_name | |
print '%-6s: %.6f' % ('MIN', arr_min) | |
print '%-6s: %.6f' % ('MAX', arr_max) | |
# Flatten input array | |
arr_1d = inarray.reshape( inarray.size, ) | |
# Define min and max for the histogram | |
x = nsig * sigma | |
mmean = numpy.median(arr_1d) | |
minhist = mmean - x | |
maxhist = mmean + x | |
ufi = inarray[ numpy.where((inarray > minhist) & (inarray < maxhist)) ] | |
# Calculate 25% and 75% percentile to get the interquartile range | |
# IRQ = pc75-pc25 | |
# zenman, A. J. 1991. | |
sixd = numpy.argsort( ufi ) | |
ndata = ufi.size | |
pc25 = ufi[ sixd[0.25*ndata] ] | |
pc75 = ufi[ sixd[0.75*ndata] ] | |
irq = pc75 - pc25 | |
step = 2.0 * irq * ndata**(-1.0/3.0) | |
# Calculate number of bins to use | |
nbin = round(2*x / step - 1) | |
# Histogram | |
# http://www.scipy.org/Tentative_NumPy_Tutorial | |
yhist, hbin = numpy.histogram(arr_1d, range=(minhist,maxhist),bins=nbin) | |
xhist = 0.5 * ( hbin[1:] + hbin[:-1] ) | |
# Define xmin and xmax for the 2-0rder fit | |
x1 = mmean - c1*sigma | |
x2 = mmean + c2*sigma | |
# Select the points beween x1 and x2 for the fit | |
w = numpy.where((xhist > x1) & (xhist < x2) & (yhist > 0)) | |
count = len(w[0]) | |
xwg = xhist[w] | |
nywg = yhist[w] | |
if count < 2: | |
print ' ' | |
print '%s: Singular matrix' % func_name | |
print '%-6s: %.6f' % ('X[W]', xwg) | |
print '%-6s: %.6f' % ('NY[W]', nywg) | |
print '%-6s: %.6f' % ('MEDIAN', mmean) | |
return mmean, sigma | |
# Change to log scale | |
yhist = numpy.log10(yhist) | |
iyh = numpy.where( ~numpy.isinf(yhist) ) | |
xhist = xhist[iyh] | |
yhist = yhist[iyh] | |
nywg = numpy.log10(nywg) | |
# Calculate the fit coefficients | |
ymax = nywg.max() | |
# Gaussian | |
# http://www.scipy.org/Cookbook/FittingData | |
if func == 1: | |
if verbose: print '%s: Fitting gaussian' % func_name | |
# Initial guess | |
ysum = numpy.sum(nywg) | |
mmean = numpy.sum(xwg * nywg) / ysum | |
sigma = numpy.sqrt(numpy.abs(numpy.sum((xwg-mmean)**2*nywg)/ysum)) | |
params = (ymax, mmean, sigma) | |
# Error function to minimize | |
errorfunction = lambda p: scipy.ravel(gaussian(*p)(xhist) - yhist) | |
# Linear least square fitting | |
a_opt, a_success = optimize.leastsq(errorfunction, params) | |
ymax = a_opt[0] | |
mmean = a_opt[1] | |
sigma = a_opt[2] | |
# Fit to entire range | |
yall = ymax * numpy.exp(-(xhist-mmean)**2/(2.0*sigma**2)) | |
# 2nd degree polynomial | |
else: | |
if verbose: print '%s: Fitting 2nd deg polynomial' % func_name | |
# Polynomial | |
a_opt = numpy.polyfit(xwg, nywg, 2) | |
mmean = -0.5*a_opt[1]/a_opt[0] | |
sigma = numpy.sqrt(-0.5 / ( a_opt[0]*numpy.log(10) ) ) | |
# Fit to entire range | |
yall = a_opt[0]*xhist**2 + a_opt[1]*xhist + a_opt[2] | |
# Print results | |
if verbose: | |
print ' ' | |
print '%s: Results' % func_name | |
print '%-6s: %.6f' % ('MODE', mmean) | |
print '%-6s: %.6f' % ('SIGMA', sigma) | |
print ' ' | |
plot_y1 = 0 | |
plot_y2 = ymax + 0.1 | |
# Plot results | |
if do_plot: | |
pylab.clf() | |
# Data points | |
pylab.plot(xhist, yhist, 'ko') | |
# Mark fitted region | |
pylab.plot(xwg, nywg, 'bo', hold=1) | |
# Draw fitted function | |
pylab.plot(xhist, yall, 'r--', hold=1) | |
pylab.axvline(x=mmean, color='r') | |
# Plot xmin xmax for the fit | |
pylab.axvline(x=x1, ymin=0, ymax=0.1, color='b') | |
pylab.axvline(x=x2, ymin=0, ymax=0.1, color='b') | |
# Axis limits and labels | |
pylab.axis([minhist, maxhist, plot_y1, plot_y2]) | |
pylab.xlabel('Pix value') | |
pylab.ylabel('Log num of pix') | |
pylab.title(ptitle) | |
#pylab.show() | |
# Pause for visual examination of plot | |
x_user = raw_input('ENTER ANY CHAR TO CONTINUE: ') | |
return mmean, sigma | |
def gaussian(height, center_x, width_x): | |
""" | |
Returns a gaussian function with the given parameters. | |
This is used for least square fitting optimization. | |
.. note:: This is used by `msky`. | |
Parameters | |
---------- | |
height: float | |
Peak amplitude. | |
center_x: float | |
Peak location. | |
width_x: float | |
Sigma of gaussian curve. | |
Returns | |
------- | |
x: lambda function | |
Function used for optimization. | |
""" | |
return lambda x: height * numpy.exp(-(center_x-x)**2/(2.0*width_x**2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment