def test_calculate_bin_edges_raises_1_val(): """ Test we get a ValueError with a single value array. """ a = np.array([5]) binning.calculate_bin_edges(a)
def test_calculate_bin_edges_raises_not_1d(): """ Test we get a ValueError with a non-1D array. """ a = np.arange(20).reshape((4, 5)) binning.calculate_bin_edges(a)
def test_center_edge_center_roundtrip(): """ Test that we can start with centers and roundtrip to the same centers. """ centers = [1, 2, 4, 10, 20] calc_edges = binning.calculate_bin_edges(centers) calc_centers = binning.calculate_bin_centers(calc_edges) np.testing.assert_array_equal(calc_centers, centers)
def test_calculate_bin_edges_uneven(): """ Test bin edges calculated for an unevenly spaced set of centers. """ centers = 2.0**np.arange(1, 10) edges = binning.calculate_bin_edges(centers) ref = [1, 3, 6, 12, 24, 48, 96, 192, 384, 640] np.testing.assert_array_equal(edges, ref)
def test_calculate_bin_edges_even(): """ Test bin edges calculated for an evenly spaced set of centers. """ centers = np.arange(10, 20, dtype=np.float) edges = binning.calculate_bin_edges(centers) ref = np.arange(9.5, 20) np.testing.assert_array_equal(edges, ref)
def test_calculate_bin_edges_uneven(): """ Test bin edges calculated for an unevenly spaced set of centers. """ centers = 2.0 ** np.arange(1, 10) edges = binning.calculate_bin_edges(centers) ref = [1, 3, 6, 12, 24, 48, 96, 192, 384, 640] np.testing.assert_array_equal(edges, ref)
def test_counts2(): counts = units.Counts() wave = refs._default_waveset flux = np.ones_like(wave) delta_wave = \ binning.calculate_bin_widths(binning.calculate_bin_edges(wave)) ref = flux / (delta_wave * refs.PRIMARY_AREA) test = counts.ToPhotlam(wave, flux) np.testing.assert_allclose(ref, test)
def test_obmag2(): ob = units.OBMag() wave = refs._default_waveset flux = np.ones_like(wave) delta_wave = \ binning.calculate_bin_widths(binning.calculate_bin_edges(wave)) ref = 10.0**(-0.4 * flux) / (delta_wave * refs.PRIMARY_AREA) test = ob.ToPhotlam(wave, flux) np.testing.assert_allclose(ref, test)
def test_counts1(): area = 1.0 counts = units.Counts() wave = refs._default_waveset flux = np.ones_like(wave) delta_wave = \ binning.calculate_bin_widths(binning.calculate_bin_edges(wave)) ref = flux / delta_wave test = counts.ToPhotlam(wave, flux, area=area) np.testing.assert_allclose(ref, test)
def test_obmag1(): area = 1.0 ob = units.OBMag() wave = refs._default_waveset flux = np.ones_like(wave) delta_wave = \ binning.calculate_bin_widths(binning.calculate_bin_edges(wave)) ref = 10.0**(-0.4 * flux) / delta_wave test = ob.ToPhotlam(wave, flux, area=area) np.testing.assert_allclose(ref, test)
def test_photlam2(): p = units.Photlam() wave = refs._default_waveset flux = np.ones_like(wave) delta_wave = \ binning.calculate_bin_widths(binning.calculate_bin_edges(wave)) ref = -1.085736 * np.log(flux * delta_wave * refs.PRIMARY_AREA) test = p.ToOBMag(wave, flux) np.testing.assert_allclose(ref, test) ref = flux * delta_wave * refs.PRIMARY_AREA test = p.ToCounts(wave, flux) np.testing.assert_allclose(ref, test)
def test_flat_spectrum(): f = FlatSpectrum(1, fluxunits='photlam') f.convert('counts') delta_wave = \ binning.calculate_bin_widths(binning.calculate_bin_edges(f.wave)) ref = delta_wave * refs.PRIMARY_AREA test = f.sample(f.wave) np.testing.assert_allclose(ref, test) f.primary_area = 100.0 ref = delta_wave * 100 test = f.sample(f.wave) np.testing.assert_allclose(ref, test)
def binning(x, y, dy=None, binwidth=None, r=None, newx=None, log=False, nan=False): """ This contains functionality for binning spectroscopy given an x, y and set of errors. This is similar to IDL's regroup but in Python (obviously). Note that y is binned as the mean(ordinates) instead of sum(ordinates), as you would want for cmputing flux in a set of pixels. User can input a constant resolution, constant binwidth or provide a user defined bin. The error is computed as sum(sqrt(sig1^2, sig2^2, sig3^2) )/3, for example if there were 3 points to bin. Parameters ---------- x : array, float vector containing abcissae. y : array,float vector containing ordinates. dy : array,float (Optional) errors on ordinates, can be float or array binwidth : float (Optional) constant bin width in same units as x r : float (Optional) constant resolution to bin to newx : array, float (Optional) new x axis to bin to log : bool (Optional) computes equal bin spacing logarithmically, Default = False sort : bool (Optional) sort into ascending order of x, default = True nan : bool (Optional) if true, this returns nan values where no points exist in a given bin Otherwise, all nans are dropped Returns ------- dict bin_y : binned ordinates bin_x : binned abcissae bin_edge : edges of bins (always contains len(bin_x)+1 elements) bin_dy : error on ordinate bin bin_n : number of points contained in each bin Examples -------- >>> from bintools import binning If you want constant resolution (using output dict from PandExo): >>> pandexo = result['FinalSpectrum'] >>> x, y, err = pandexo['wave'], pandexo['spectrum_w_rand'], pandexo['error_w_floor'] >>> final = binning(x, y, dy = err, r =100) >>> newx, newy, newerr = final['bin_x'], final['bin_y'], final['bin_dy'] If you have a x axis that you want PandExo output to be binned to >>> newx = np.linspace(1,5,10) >>> final = binning(x, y, dy = err, newx =newx) >>> newx, newy, newerr = final['bin_x'], final['bin_y'], final['bin_dy'] If you want a constant bin width and want everything to be spaced linearly >>> final = binning(x, y, dy = err, binwidth = 0.1) >>> newx, newy, newerr = final['bin_x'], final['bin_y'], final['bin_dy'] If you want constant bin width but want everything to spaced logarithmically >>> final = binning(x, y, dy = err, binwidth = 0.1, log=True) >>> newx, newy, newerr = final['bin_x'], final['bin_y'], final['bin_dy'] """ #check x and y are same length if len(x) != len(y): raise Exception('X and Y are not the same length') #check that either newx or binwidth are specified if newx is None and binwidth is None and r is None: raise Exception( 'Need to either supply new x axis, resolution, or a binwidth') if (binwidth is None) and (log): raise Exception("Cannot do logarithmic binning with out a binwidth") if newx is not None: bin_x = newx bin_x, bin_y, bin_dy, bin_n = uniform_tophat_mean(bin_x, x, y, dy=dy, nan=nan) bin_edge = astrobin.calculate_bin_edges(bin_x) return { 'bin_y': bin_y, 'bin_x': bin_x, 'bin_edge': bin_edge, 'bin_dy': bin_dy, 'bin_n': bin_n } elif r is not None: bin_x = bin_wave_to_R(x, r) bin_x, bin_y, bin_dy, bin_n = uniform_tophat_mean(bin_x, x, y, dy=dy, nan=nan) bin_edge = astrobin.calculate_bin_edges(bin_x) return { 'bin_y': bin_y, 'bin_x': bin_x, 'bin_edge': bin_edge, 'bin_dy': bin_dy, 'bin_n': bin_n } elif binwidth is not None: if (binwidth < 0) and (log): warn.warn( UserWarning( "Negative binwidth specified. Assuming this is log10(binwidth)" )) binwidth = 10**binwidth if log: bin_x = np.arange(np.log10(min(x)), np.log10(max(x)), np.log10(binwidth)) bin_x = 10**bin_x elif not log: bin_x = np.arange(min(x), max(x), binwidth) bin_x, bin_y, bin_dy, bin_n = uniform_tophat_mean(bin_x, x, y, dy=dy, nan=nan) bin_edge = astrobin.calculate_bin_edges(bin_x) return { 'bin_y': bin_y, 'bin_x': bin_x, 'bin_edge': bin_edge, 'bin_dy': bin_dy, 'bin_n': bin_n }