From 39f31e4eeae0c40883760a9f076a471bc43bb59a Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 16:24:27 -0400 Subject: [PATCH 1/8] First commit of transform class --- ccdproc/core.py | 81 +++++++++++++++++++++++++++++++++-- ccdproc/tests/test_ccdproc.py | 39 ++++++++++++++++- 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/ccdproc/core.py b/ccdproc/core.py index 2bb75380..271fe1f4 100644 --- a/ccdproc/core.py +++ b/ccdproc/core.py @@ -21,9 +21,9 @@ __all__ = ['background_variance_box', 'background_variance_filter', 'cosmicray_clean', 'cosmicray_median', 'cosmicray_lacosmic', - 'create_variance', 'flat_correct', 'gain_correct', 'sigma_func', - 'subtract_bias', 'subtract_dark', 'subtract_overscan', - 'trim_image', 'Keyword'] + 'create_variance', 'flat_correct', 'transform_image', + 'gain_correct', 'sigma_func', 'subtract_bias', 'subtract_dark', + 'subtract_overscan', 'trim_image', 'Keyword'] # The dictionary below is used to translate actual function names to names # that are FITS compliant, i.e. 8 characters or less. @@ -38,6 +38,7 @@ 'subtract_dark': 'subdark', 'subtract_overscan': 'suboscan', 'trim_image': 'trimim', + 'transform_image': 'tranim', } @@ -478,6 +479,79 @@ def flat_correct(ccd, flat, min_value=None): use_flat.unit) return flat_corrected +@log_to_metadata +def transform_image(ccd, transform_func, **kwargs): + """Transform the image + + Using the function specified by transform_func, the transform will + be applied to all planes in ccd. + + Parameters + ---------- + ccd : `~ccdproc.ccddata.CCDData` + Data to be flatfield corrected + + transform_func : function + Function to be used to transform the data + + kwargs: dict + Dictionary of arguments to be used by the transform_func. + + {log} + + Returns + ------- + ccd : `~ccdproc.ccddata.CCDData` + A transformed CCDData object + + Note + ---- + + At this time, transform will be applied to the uncertainy data but it + will only transform the data. This may not properly handle uncertainties + that arise due to correlation between the pixels. + + Examples + -------- + + Given an array that is 100x100, + + >>> import numpy as np + >>> from astropy import units as u + >>> arr1 = CCDData(np.ones([100, 100]), unit=u.adu) + + the syntax for transforming the array using + scipy.ndimage.interpolation.shift + + >>> from scipy.ndimage.interpolation import shift + >>> transformed = transform(arr1, shift, shift=(5.5, 8.1)) + + """ + #check that it is a ccddata object + if not (isinstance(ccd, CCDData)): + raise TypeError('ccd is not a CCDData') + + #check that transform is a callable function + if not hasattr(transform_func, '__call__'): + raise TypeError('transform is not a function') + + #make a copy of the object + nccd = ccd.copy() + + #transform the image plane + nccd.data = transform_func(nccd.data, **kwargs) + + #transform the uncertainty plane if it exists + if nccd.uncertainty is not None: + nccd.uncertainty.array = transform_func(nccd.uncertainty.array, + **kwargs) + + #transform the mask plane + if nccd.mask is not None: + nccd.mask = transform_func(nccd.mask, **kwargs) + nccd.mask = (nccd.mask > 0) + + return nccd def sigma_func(arr): """ @@ -836,6 +910,7 @@ def cosmicray_lacosmic(data, background, thresh=5, fthresh=5, gthresh=1.5, return crarr + def cosmicray_median(data, background, thresh=5, mbox=11): """ Identify cosmic rays through median technique. The median technique diff --git a/ccdproc/tests/test_ccdproc.py b/ccdproc/tests/test_ccdproc.py index 654c39f0..3f597f4a 100644 --- a/ccdproc/tests/test_ccdproc.py +++ b/ccdproc/tests/test_ccdproc.py @@ -1,5 +1,5 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst -# This module implements the base CCDData class. +# This module implements the base CCDData class from __future__ import (absolute_import, division, print_function, unicode_literals) @@ -207,6 +207,7 @@ def test_trim_image_fits_section(ccd_data, mask_data, uncertainty): assert trimmed.shape == trimmed.uncertainty.array.shape + @pytest.mark.data_size(50) def test_trim_image_no_section(ccd_data): trimmed = trim_image(ccd_data[:, 19:40]) @@ -386,6 +387,42 @@ def test_gain_correct_quantity(ccd_data): assert_array_equal(ccd_data.data, 3 * init_data) assert ccd_data.unit == u.electron +#test transform is ccd +def test_transform_isccd(ccd_data): + with pytest.raises(TypeError): + transform_image(1, 1) + +#test function is callable +def test_transform_isfunc(ccd_data): + with pytest.raises(TypeError): + transform_image(ccd_data, 1) + +@pytest.mark.parametrize('mask_data, uncertainty', [ + (False, False), + (True, True)]) +@pytest.mark.data_size(50) +def test_transform_image(ccd_data, mask_data, uncertainty): + if mask_data: + ccd_data.mask = np.zeros_like(ccd_data) + ccd_data.mask[10,10] = 1 + if uncertainty: + err = np.random.normal(size=ccd_data.shape) + ccd_data.uncertainty = StdDevUncertainty(err) + def tran(arr): + return 10 * arr + + tran = transform_image(ccd_data, tran) + + assert_array_equal(10 * ccd_data.data, tran.data) + if mask_data: + assert tran.shape == tran.mask.shape + assert_array_equal(ccd_data.mask, tran.mask) + if uncertainty: + assert tran.shape == tran.uncertainty.array.shape + assert_array_equal(10 * ccd_data.uncertainty.array, tran.uncertainty.array) + + + #test rebinning ndarray def test__rebin_ndarray(ccd_data): with pytest.raises(TypeError): From f6c1c89e07c141ddf2ec6cfb610f5c2bbfe3ac0b Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 16:29:53 -0400 Subject: [PATCH 2/8] pep8 fixes to test_ccdproc.py --- ccdproc/tests/test_ccdproc.py | 50 ++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/ccdproc/tests/test_ccdproc.py b/ccdproc/tests/test_ccdproc.py index 3f597f4a..f51df3cc 100644 --- a/ccdproc/tests/test_ccdproc.py +++ b/ccdproc/tests/test_ccdproc.py @@ -18,6 +18,7 @@ from ..core import * from ..core import _rebin, _blkavg + # test creating variance # success expected if u_image * u_gain = u_readnoise @pytest.mark.parametrize('u_image,u_gain,u_readnoise,expect_succes', [ @@ -207,7 +208,6 @@ def test_trim_image_fits_section(ccd_data, mask_data, uncertainty): assert trimmed.shape == trimmed.uncertainty.array.shape - @pytest.mark.data_size(50) def test_trim_image_no_section(ccd_data): trimmed = trim_image(ccd_data[:, 19:40]) @@ -369,8 +369,6 @@ def test_flat_correct_variance(ccd_data): flat = create_variance(flat, readnoise=0.5 * u.electron) ccd_data = flat_correct(ccd_data, flat) - - # tests for gain correction def test_gain_correct(ccd_data): @@ -387,16 +385,19 @@ def test_gain_correct_quantity(ccd_data): assert_array_equal(ccd_data.data, 3 * init_data) assert ccd_data.unit == u.electron + #test transform is ccd def test_transform_isccd(ccd_data): with pytest.raises(TypeError): transform_image(1, 1) + #test function is callable def test_transform_isfunc(ccd_data): with pytest.raises(TypeError): transform_image(ccd_data, 1) + @pytest.mark.parametrize('mask_data, uncertainty', [ (False, False), (True, True)]) @@ -404,10 +405,11 @@ def test_transform_isfunc(ccd_data): def test_transform_image(ccd_data, mask_data, uncertainty): if mask_data: ccd_data.mask = np.zeros_like(ccd_data) - ccd_data.mask[10,10] = 1 + ccd_data.mask[10, 10] = 1 if uncertainty: err = np.random.normal(size=ccd_data.shape) ccd_data.uncertainty = StdDevUncertainty(err) + def tran(arr): return 10 * arr @@ -419,14 +421,15 @@ def tran(arr): assert_array_equal(ccd_data.mask, tran.mask) if uncertainty: assert tran.shape == tran.uncertainty.array.shape - assert_array_equal(10 * ccd_data.uncertainty.array, tran.uncertainty.array) - + assert_array_equal(10 * ccd_data.uncertainty.array, + tran.uncertainty.array) #test rebinning ndarray def test__rebin_ndarray(ccd_data): with pytest.raises(TypeError): - _rebin(1, (5,5)) + _rebin(1, (5, 5)) + #test rebinning dimensions @pytest.mark.data_size(10) @@ -434,29 +437,33 @@ def test__rebin_dimensions(ccd_data): with pytest.raises(ValueError): _rebin(ccd_data.data, (5,)) + #test rebinning works @pytest.mark.data_size(10) def test__rebin_larger(ccd_data): - a = ccd_data.data - b = _rebin(a, (20,20)) + a = ccd_data.data + b = _rebin(a, (20, 20)) + + assert b.shape == (20, 20) + np.testing.assert_almost_equal(b.sum(), 4 * a.sum()) - assert b.shape == (20,20) - np.testing.assert_almost_equal(b.sum(), 4 * a.sum()) #test rebinning is invariant @pytest.mark.data_size(10) def test__rebin_smaller(ccd_data): - a = ccd_data.data - b = _rebin(a, (20, 20)) - c = _rebin(b, (10, 10)) + a = ccd_data.data + b = _rebin(a, (20, 20)) + c = _rebin(b, (10, 10)) + + assert c.shape == (10, 10) + assert (c-a).sum() == 0 - assert c.shape == (10,10) - assert (c-a).sum() == 0 #test blockaveraging ndarray def test__blkavg_ndarray(ccd_data): with pytest.raises(TypeError): - _blkavg(1, (5,5)) + _blkavg(1, (5, 5)) + #test rebinning dimensions @pytest.mark.data_size(10) @@ -464,11 +471,12 @@ def test__blkavg_dimensions(ccd_data): with pytest.raises(ValueError): _blkavg(ccd_data.data, (5,)) + #test blkavg works @pytest.mark.data_size(20) def test__blkavg_larger(ccd_data): - a = ccd_data.data - b = _blkavg(a, (10,10)) + a = ccd_data.data + b = _blkavg(a, (10, 10)) - assert b.shape == (10,10) - np.testing.assert_almost_equal(b.sum(), 0.25 * a.sum()) + assert b.shape == (10, 10) + np.testing.assert_almost_equal(b.sum(), 0.25 * a.sum()) From 260808f6f796fe293813a4b13cafba0cee413ac0 Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 16:40:54 -0400 Subject: [PATCH 3/8] pep8 fixes --- ccdproc/core.py | 57 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/ccdproc/core.py b/ccdproc/core.py index 271fe1f4..2ac448d5 100644 --- a/ccdproc/core.py +++ b/ccdproc/core.py @@ -22,7 +22,7 @@ __all__ = ['background_variance_box', 'background_variance_filter', 'cosmicray_clean', 'cosmicray_median', 'cosmicray_lacosmic', 'create_variance', 'flat_correct', 'transform_image', - 'gain_correct', 'sigma_func', 'subtract_bias', 'subtract_dark', + 'gain_correct', 'sigma_func', 'subtract_bias', 'subtract_dark', 'subtract_overscan', 'trim_image', 'Keyword'] # The dictionary below is used to translate actual function names to names @@ -479,9 +479,10 @@ def flat_correct(ccd, flat, min_value=None): use_flat.unit) return flat_corrected + @log_to_metadata def transform_image(ccd, transform_func, **kwargs): - """Transform the image + """Transform the image Using the function specified by transform_func, the transform will be applied to all planes in ccd. @@ -502,14 +503,14 @@ def transform_image(ccd, transform_func, **kwargs): Returns ------- ccd : `~ccdproc.ccddata.CCDData` - A transformed CCDData object + A transformed CCDData object Note ---- - At this time, transform will be applied to the uncertainy data but it + At this time, transform will be applied to the uncertainy data but it will only transform the data. This may not properly handle uncertainties - that arise due to correlation between the pixels. + that arise due to correlation between the pixels. Examples -------- @@ -520,8 +521,8 @@ def transform_image(ccd, transform_func, **kwargs): >>> from astropy import units as u >>> arr1 = CCDData(np.ones([100, 100]), unit=u.adu) - the syntax for transforming the array using - scipy.ndimage.interpolation.shift + the syntax for transforming the array using + scipy.ndimage.interpolation.shift >>> from scipy.ndimage.interpolation import shift >>> transformed = transform(arr1, shift, shift=(5.5, 8.1)) @@ -538,7 +539,7 @@ def transform_image(ccd, transform_func, **kwargs): #make a copy of the object nccd = ccd.copy() - #transform the image plane + #transform the image plane nccd.data = transform_func(nccd.data, **kwargs) #transform the uncertainty plane if it exists @@ -553,6 +554,7 @@ def transform_image(ccd, transform_func, **kwargs): return nccd + def sigma_func(arr): """ Robust method for calculating the variance of an array. ``sigma_func`` uses @@ -775,23 +777,23 @@ def _blkavg(data, newshape): raise TypeError('data is not a ndarray object') #check to see that the two arrays are going to be the same length - if len(data.shape)!=len(newshape): + if len(data.shape) != len(newshape): raise ValueError('newshape does not have the same dimensions as data') - shape=data.shape + shape = data.shape lenShape = len(shape) factor = np.asarray(shape)/np.asarray(newshape) evList = ['data.reshape('] + \ - ['newshape[%d],factor[%d],'%(i,i) for i in range(lenShape)] + \ - [')'] + ['.mean(%d)'%(i+1) for i in range(lenShape)] + ['newshape[%d],factor[%d],' % (i, i) for i in range(lenShape)] + \ + [')'] + ['.mean(%d)' % (i + 1) for i in range(lenShape)] return eval(''.join(evList)) -def cosmicray_lacosmic(data, background, thresh=5, fthresh=5, gthresh=1.5, - b_factor=2, mbox = 5, min_limit=0.01, - f_conv=np.array([[0,-1,0],[-1,4,-1],[0,-1,0]])): +def cosmicray_lacosmic(data, background, thresh=5, fthresh=5, + gthresh=1.5, b_factor=2, mbox=5, min_limit=0.01, + f_conv=np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])): """ Identify cosmic rays through the lacosmic technique. The lacosmic technique identifies cosmic rays by identifying pixels based on a variation of the @@ -863,18 +865,18 @@ def cosmicray_lacosmic(data, background, thresh=5, fthresh=5, gthresh=1.5, raise ValueError('background is not the same shape as data') #set up a copy of the array and original shape - shape=data.shape + shape = data.shape #rebin the data - newshape = (b_factor*shape[0],b_factor*shape[1]) + newshape = (b_factor*shape[0], b_factor*shape[1]) ldata = _rebin(data, newshape) #convolve with f_conv - ldata=ndimage.filters.convolve(ldata,f_conv) - ldata[ldata<=0] = 0 + ldata = ndimage.filters.convolve(ldata, f_conv) + ldata[ldata <= 0] = 0 #return to the original binning - ldata = _blkavg(ldata,shape) + ldata = _blkavg(ldata, shape) #median the noise image med_noise = ndimage.median_filter(background, size=(mbox, mbox)) @@ -887,30 +889,29 @@ def cosmicray_lacosmic(data, background, thresh=5, fthresh=5, gthresh=1.5, sndata = sndata - mdata #select objects - masks = (sndata>thresh) + masks = (sndata > thresh) #remove compact bright sources - fdata = ndimage.median_filter(data, size=(mbox-2, mbox-2)) - fdata -= ndimage.median_filter(data, size=(mbox+2, mbox+2)) + fdata = ndimage.median_filter(data, size=(mbox-2, mbox-2)) + fdata = fdata - ndimage.median_filter(data, size=(mbox+2, mbox+2)) fdata = fdata / med_noise # set a minimum value for all pixels so no divide by zero problems - fdata[fdata fthresh) #make the list of cosmic rays - crarr = masks * (fdata > fthresh) + crarr = masks * (fdata > fthresh) #check any of the neighboring pixels - gdata = sndata * ndimage.filters.maximum_filter(crarr,size=(3,3)) + gdata = sndata * ndimage.filters.maximum_filter(crarr, size=(3, 3)) crarr = crarr * (gdata > gthresh) return crarr - def cosmicray_median(data, background, thresh=5, mbox=11): """ Identify cosmic rays through median technique. The median technique @@ -1029,7 +1030,7 @@ def cosmicray_clean(ccd, thresh, cr_func, crargs={}, estimated in a box around the image. It will then replace bad pixel value with the median of the pixels in an 11 pixel wide box around the bad pixel. - >>> from ccdproc import background_variance_box,cosmicray_median, cosmicray_clean + >>> from ccdproc import background_variance_box, cosmicray_median, cosmicray_clean >>> cosmicray_clean(ccddata, 10, cosmicray_median, crargs=(11,), background=background_variance_box, bargs=(25,), rbox=11) From 462537349f5e52a85699538ac7112a0f2ea6282f Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 17:07:49 -0400 Subject: [PATCH 4/8] added rebin task --- ccdproc/core.py | 82 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/ccdproc/core.py b/ccdproc/core.py index 2ac448d5..93481898 100644 --- a/ccdproc/core.py +++ b/ccdproc/core.py @@ -21,9 +21,9 @@ __all__ = ['background_variance_box', 'background_variance_filter', 'cosmicray_clean', 'cosmicray_median', 'cosmicray_lacosmic', - 'create_variance', 'flat_correct', 'transform_image', - 'gain_correct', 'sigma_func', 'subtract_bias', 'subtract_dark', - 'subtract_overscan', 'trim_image', 'Keyword'] + 'create_variance', 'flat_correct', 'gain_correct', 'rebin', + 'sigma_func', 'subtract_bias', 'subtract_dark', 'subtract_overscan', + 'transform_image', 'trim_image', 'Keyword'] # The dictionary below is used to translate actual function names to names # that are FITS compliant, i.e. 8 characters or less. @@ -505,8 +505,8 @@ def transform_image(ccd, transform_func, **kwargs): ccd : `~ccdproc.ccddata.CCDData` A transformed CCDData object - Note - ---- + Notes + ----- At this time, transform will be applied to the uncertainy data but it will only transform the data. This may not properly handle uncertainties @@ -691,13 +691,13 @@ def background_variance_filter(data, bbox): return ndimage.generic_filter(data, sigma_func, size=(bbox, bbox)) -def _rebin(data, newshape): +def rebin(ccd, newshape): """ Rebin an array to have a new shape Parameters ---------- - data : `~numpy.ndarray` + data : `~ccdproc.CCDData` or `~numpy.ndarray` Data to rebin newshape : tuple @@ -705,13 +705,15 @@ def _rebin(data, newshape): Returns ------- - output : `~numpy.ndarray` - An array with the new shape + output : `~ccdproc.CCDData` or `~numpy.ndarray` + An array with the new shape. It will have the same type as the input + object. Raises ------ TypeError - A type error is raised if data is not an `numpy.ndarray` + A type error is raised if data is not an `numpy.ndarray` or + `~ccdproc.CCDData` ValueError A value error is raised if the dimenisions of new shape is not equal @@ -722,23 +724,57 @@ def _rebin(data, newshape): This is based on the scipy cookbook for rebinning: http://wiki.scipy.org/Cookbook/Rebinning + If rebinning a CCDData object to a smaller shape, there is no guarantee that the + masking or uncertainty are handled correctly + Examples -------- + Given an array that is 100x100, - """ - #check to see that is in a nddata type - if not isinstance(data, np.ndarray): - raise TypeError('data is not a ndarray object') + >>> import numpy as np + >>> from astropy import units as u + >>> arr1 = CCDData(np.ones([10, 10]), unit=u.adu) - #check to see that the two arrays are going to be the same length - if len(data.shape) != len(newshape): - raise ValueError('newshape does not have the same dimensions as data') + the syntax for rebinning an array to a shape + of (20,20) is - slices = [slice(0, old, float(old)/new) for old, new in - zip(data.shape, newshape)] - coordinates = np.mgrid[slices] - indices = coordinates.astype('i') - return data[tuple(indices)] + >>> rebinned = rebin(arr1, (20,20)) + + + """ + #check to see that is in a nddata type + if isinstance(ccd, np.ndarray): + + #check to see that the two arrays are going to be the same length + if len(ccd.shape) != len(newshape): + raise ValueError('newshape does not have the same dimensions as ccd') + + slices = [slice(0, old, float(old)/new) for old, new in + zip(ccd.shape, newshape)] + coordinates = np.mgrid[slices] + indices = coordinates.astype('i') + return ccd[tuple(indices)] + + elif isinstance(ccd, CCDData): + #check to see that the two arrays are going to be the same length + if len(ccd.shape) != len(newshape): + raise ValueError('newshape does not have the same dimensions as ccd') + + nccd = ccd.copy() + #rebin the data plane + nccd.data = rebin(nccd.data, newshape) + + #rebin the uncertainty plane + if nccd.uncertainty is not None: + nccd.uncertainty.array = rebin(nccd.uncertainty.array, newshape) + + #rebin the mask plane + if nccd.mask is not None: + nccd.mask = rebin(nccd.mask, newshape) + + return nccd + else: + raise TypeError('ccd is not an ndarray or a CCDData object') def _blkavg(data, newshape): @@ -869,7 +905,7 @@ def cosmicray_lacosmic(data, background, thresh=5, fthresh=5, #rebin the data newshape = (b_factor*shape[0], b_factor*shape[1]) - ldata = _rebin(data, newshape) + ldata = rebin(data, newshape) #convolve with f_conv ldata = ndimage.filters.convolve(ldata, f_conv) From 3b89bc241f41fc9e37b8ab0b88d55dec836b8327 Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 17:08:13 -0400 Subject: [PATCH 5/8] added tests for rebinning --- ccdproc/tests/test_ccdproc.py | 47 +++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/ccdproc/tests/test_ccdproc.py b/ccdproc/tests/test_ccdproc.py index f51df3cc..e6c13f80 100644 --- a/ccdproc/tests/test_ccdproc.py +++ b/ccdproc/tests/test_ccdproc.py @@ -16,7 +16,7 @@ from ..ccddata import CCDData from ..core import * -from ..core import _rebin, _blkavg +from ..core import _blkavg # test creating variance @@ -426,23 +426,29 @@ def tran(arr): #test rebinning ndarray -def test__rebin_ndarray(ccd_data): +def test_rebin_ndarray(ccd_data): with pytest.raises(TypeError): - _rebin(1, (5, 5)) + rebin(1, (5, 5)) #test rebinning dimensions @pytest.mark.data_size(10) -def test__rebin_dimensions(ccd_data): +def test_rebin_dimensions(ccd_data): with pytest.raises(ValueError): - _rebin(ccd_data.data, (5,)) + rebin(ccd_data.data, (5,)) + +#test rebinning dimensions +@pytest.mark.data_size(10) +def test_rebin_ccddata_dimensions(ccd_data): + with pytest.raises(ValueError): + rebin(ccd_data, (5,)) #test rebinning works @pytest.mark.data_size(10) -def test__rebin_larger(ccd_data): +def test_rebin_larger(ccd_data): a = ccd_data.data - b = _rebin(a, (20, 20)) + b = rebin(a, (20, 20)) assert b.shape == (20, 20) np.testing.assert_almost_equal(b.sum(), 4 * a.sum()) @@ -450,14 +456,35 @@ def test__rebin_larger(ccd_data): #test rebinning is invariant @pytest.mark.data_size(10) -def test__rebin_smaller(ccd_data): +def test_rebin_smaller(ccd_data): a = ccd_data.data - b = _rebin(a, (20, 20)) - c = _rebin(b, (10, 10)) + b = rebin(a, (20, 20)) + c = rebin(b, (10, 10)) assert c.shape == (10, 10) assert (c-a).sum() == 0 +#test rebinning with ccddata object +@pytest.mark.parametrize('mask_data, uncertainty', [ + (False, False), + (True, True)]) +@pytest.mark.data_size(10) +def test_rebin_ccddata(ccd_data, mask_data, uncertainty): + if mask_data: + ccd_data.mask = np.zeros_like(ccd_data) + if uncertainty: + err = np.random.normal(size=ccd_data.shape) + ccd_data.uncertainty = StdDevUncertainty(err) + + b = rebin(ccd_data, (20, 20)) + + assert b.shape == (20,20) + if mask_data: + assert b.mask.shape == (20,20) + if uncertainty: + assert b.uncertainty.array.shape == (20,20) + + #test blockaveraging ndarray def test__blkavg_ndarray(ccd_data): From ec5eb5a63ab526df2e6e037d6e2eec6c20cb74d7 Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 17:11:59 -0400 Subject: [PATCH 6/8] pep8 fixes in core.py --- ccdproc/core.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ccdproc/core.py b/ccdproc/core.py index 93481898..ca3dc2b8 100644 --- a/ccdproc/core.py +++ b/ccdproc/core.py @@ -707,12 +707,12 @@ def rebin(ccd, newshape): ------- output : `~ccdproc.CCDData` or `~numpy.ndarray` An array with the new shape. It will have the same type as the input - object. + object. Raises ------ TypeError - A type error is raised if data is not an `numpy.ndarray` or + A type error is raised if data is not an `numpy.ndarray` or `~ccdproc.CCDData` ValueError @@ -724,8 +724,8 @@ def rebin(ccd, newshape): This is based on the scipy cookbook for rebinning: http://wiki.scipy.org/Cookbook/Rebinning - If rebinning a CCDData object to a smaller shape, there is no guarantee that the - masking or uncertainty are handled correctly + If rebinning a CCDData object to a smaller shape, the masking and + uncertainty are not handled correctly. Examples -------- @@ -736,11 +736,10 @@ def rebin(ccd, newshape): >>> arr1 = CCDData(np.ones([10, 10]), unit=u.adu) the syntax for rebinning an array to a shape - of (20,20) is + of (20,20) is >>> rebinned = rebin(arr1, (20,20)) - """ #check to see that is in a nddata type if isinstance(ccd, np.ndarray): @@ -761,17 +760,17 @@ def rebin(ccd, newshape): raise ValueError('newshape does not have the same dimensions as ccd') nccd = ccd.copy() - #rebin the data plane + #rebin the data plane nccd.data = rebin(nccd.data, newshape) #rebin the uncertainty plane if nccd.uncertainty is not None: - nccd.uncertainty.array = rebin(nccd.uncertainty.array, newshape) + nccd.uncertainty.array = rebin(nccd.uncertainty.array, newshape) - #rebin the mask plane + #rebin the mask plane if nccd.mask is not None: - nccd.mask = rebin(nccd.mask, newshape) - + nccd.mask = rebin(nccd.mask, newshape) + return nccd else: raise TypeError('ccd is not an ndarray or a CCDData object') From ff4d2fa51a7d5a5c32620088e2ca1f3316f7046a Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Thu, 3 Jul 2014 17:13:33 -0400 Subject: [PATCH 7/8] pep8 fixes to test_ccdproc.py --- ccdproc/tests/test_ccdproc.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ccdproc/tests/test_ccdproc.py b/ccdproc/tests/test_ccdproc.py index e6c13f80..5f9efa52 100644 --- a/ccdproc/tests/test_ccdproc.py +++ b/ccdproc/tests/test_ccdproc.py @@ -437,6 +437,7 @@ def test_rebin_dimensions(ccd_data): with pytest.raises(ValueError): rebin(ccd_data.data, (5,)) + #test rebinning dimensions @pytest.mark.data_size(10) def test_rebin_ccddata_dimensions(ccd_data): @@ -464,6 +465,7 @@ def test_rebin_smaller(ccd_data): assert c.shape == (10, 10) assert (c-a).sum() == 0 + #test rebinning with ccddata object @pytest.mark.parametrize('mask_data, uncertainty', [ (False, False), @@ -478,12 +480,11 @@ def test_rebin_ccddata(ccd_data, mask_data, uncertainty): b = rebin(ccd_data, (20, 20)) - assert b.shape == (20,20) + assert b.shape == (20, 20) if mask_data: - assert b.mask.shape == (20,20) + assert b.mask.shape == (20, 20) if uncertainty: - assert b.uncertainty.array.shape == (20,20) - + assert b.uncertainty.array.shape == (20, 20) #test blockaveraging ndarray From bf0cd8a51b1c1a2356333c6b6dd7861323e1dbfb Mon Sep 17 00:00:00 2001 From: Steven Crawford Date: Tue, 8 Jul 2014 11:45:53 -0400 Subject: [PATCH 8/8] updates from Matt's comments --- ccdproc/core.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ccdproc/core.py b/ccdproc/core.py index ca3dc2b8..5048871c 100644 --- a/ccdproc/core.py +++ b/ccdproc/core.py @@ -485,7 +485,7 @@ def transform_image(ccd, transform_func, **kwargs): """Transform the image Using the function specified by transform_func, the transform will - be applied to all planes in ccd. + be applied to data, uncertainty, and mask in ccd. Parameters ---------- @@ -509,9 +509,12 @@ def transform_image(ccd, transform_func, **kwargs): ----- At this time, transform will be applied to the uncertainy data but it - will only transform the data. This may not properly handle uncertainties + will only transform the data. This will not properly handle uncertainties that arise due to correlation between the pixels. + These should only be geometric transformations of the images. Other + methods should be used if the units of ccd need to be changed. + Examples -------- @@ -549,8 +552,8 @@ def transform_image(ccd, transform_func, **kwargs): #transform the mask plane if nccd.mask is not None: - nccd.mask = transform_func(nccd.mask, **kwargs) - nccd.mask = (nccd.mask > 0) + mask = transform_func(nccd.mask, **kwargs) + nccd.mask = (mask > 0) return nccd @@ -693,7 +696,7 @@ def background_variance_filter(data, bbox): def rebin(ccd, newshape): """ - Rebin an array to have a new shape + Rebin an array to have a new shape. Parameters ---------- @@ -748,7 +751,7 @@ def rebin(ccd, newshape): if len(ccd.shape) != len(newshape): raise ValueError('newshape does not have the same dimensions as ccd') - slices = [slice(0, old, float(old)/new) for old, new in + slices = [slice(0, old, old/new) for old, new in zip(ccd.shape, newshape)] coordinates = np.mgrid[slices] indices = coordinates.astype('i')