From c1cb84822928d95ef2305ed214ebc9d02f9c71dc Mon Sep 17 00:00:00 2001 From: Matthew Craig Date: Thu, 22 May 2014 02:38:25 -0500 Subject: [PATCH 1/2] Switch metadata to a case-insensitive ordered dict --- ccdproc/ccddata.py | 20 +++++++++++--------- ccdproc/tests/test_ccddata.py | 14 +++++++++++--- ccdproc/tests/test_ccdproc_logging.py | 2 +- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/ccdproc/ccddata.py b/ccdproc/ccddata.py index a49ce3f1..a877b3c4 100644 --- a/ccdproc/ccddata.py +++ b/ccdproc/ccddata.py @@ -13,6 +13,8 @@ from astropy import units as u import astropy +from .utils.collections import CaseInsensitiveOrderedDict + adu = u.adu electron = u.def_unit('electron') photon = u.photon @@ -118,11 +120,9 @@ def meta(self): @meta.setter def meta(self, value): if value is None: - self._meta = fits.Header() - elif isinstance(value, fits.Header): - self._meta = value + self._meta = CaseInsensitiveOrderedDict() else: - h = fits.Header() + h = CaseInsensitiveOrderedDict() try: for k, v in value.items(): h[k] = v @@ -130,7 +130,6 @@ def meta(self, value): raise TypeError('NDData meta attribute must be dict-like') self._meta = h - @property def uncertainty(self): return self._uncertainty @@ -148,7 +147,7 @@ def uncertainty(self, value): self._uncertainty = value def to_hdu(self): - """Creates an HDUList object from a CCDData object + """Creates an HDUList object from a CCDData object. Raises ------- @@ -160,13 +159,16 @@ def to_hdu(self): hdulist : astropy.io.fits.HDUList object """ - hdu = fits.PrimaryHDU(self.data, self.header) + header = fits.Header() + for k, v in self.header.items(): + header[k] = v + hdu = fits.PrimaryHDU(self.data, header) hdulist = fits.HDUList([hdu]) return hdulist def copy(self): """ - Return a copy of the CCDData object + Return a copy of the CCDData object. """ return copy.deepcopy(self) @@ -288,7 +290,7 @@ def fits_ccddata_writer(ccd_data, filename, **kwd): kwd : All additional keywords are passed to :py:mod:`astropy.io.fits` """ - hdu = fits.PrimaryHDU(data=ccd_data.data, header=ccd_data.header) + hdu = ccd_data.to_hdu() hdu.writeto(filename, **kwd) diff --git a/ccdproc/tests/test_ccddata.py b/ccdproc/tests/test_ccddata.py index ddb999e4..ca977945 100644 --- a/ccdproc/tests/test_ccddata.py +++ b/ccdproc/tests/test_ccddata.py @@ -39,7 +39,8 @@ def test_initialize_from_FITS(ccd_data, tmpdir): assert cd.shape == (10, 10) assert cd.size == 100 assert np.issubdtype(cd.data.dtype, np.float) - assert cd.meta == hdu.header + for k, v in hdu.header.items(): + assert cd.meta[k] == v def test_initialize_from_FITS_bad_keyword_raises_error(ccd_data, tmpdir): @@ -63,9 +64,16 @@ def test_ccddata_writer(ccd_data, tmpdir): np.testing.assert_array_equal(ccd_data.data, ccd_disk.data) -def test_ccddata_meta_is_fits_header(ccd_data): +def test_ccddata_meta_is_case_insensitive(ccd_data): + key = 'SoMeKEY' + ccd_data.meta[key] = 10 + assert key.lower() in ccd_data.meta + assert key.upper() in ccd_data.meta + + +def test_ccddata_meta_is_not_fits_header(ccd_data): ccd_data.meta = {'OBSERVER': 'Edwin Hubble'} - assert isinstance(ccd_data.meta, fits.Header) + assert not isinstance(ccd_data.meta, fits.Header) def test_fromMEF(ccd_data, tmpdir): diff --git a/ccdproc/tests/test_ccdproc_logging.py b/ccdproc/tests/test_ccdproc_logging.py index 2b841955..7763bad0 100644 --- a/ccdproc/tests/test_ccdproc_logging.py +++ b/ccdproc/tests/test_ccdproc_logging.py @@ -18,7 +18,7 @@ def test_log_string(ccd_data, key): assert add_key not in ccd_data.meta # Long keyword names should be accessible with just the keyword name # without HIERARCH -- is it? - assert new.meta[add_key] == '' + assert new.meta[add_key] is None def test_log_keyword(ccd_data): From dbd8acf2024d120702630c3e6470661c034c6e44 Mon Sep 17 00:00:00 2001 From: Matthew Craig Date: Thu, 22 May 2014 02:40:32 -0500 Subject: [PATCH 2/2] Add the file containing CaseInsensitiveOrderedDict Closes #78 --- ccdproc/utils/collections.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 ccdproc/utils/collections.py diff --git a/ccdproc/utils/collections.py b/ccdproc/utils/collections.py new file mode 100644 index 00000000..222d977f --- /dev/null +++ b/ccdproc/utils/collections.py @@ -0,0 +1,35 @@ +""" +Useful objects based on collections +""" + +from __future__ import (absolute_import, print_function) + +from astropy.utils.compat.odict import OrderedDict + + +class CaseInsensitiveOrderedDict(OrderedDict): + """ + docstring for CaseInsensitiveOrderedDict + """ + + def __init__(self, *arg, **kwd): + super(CaseInsensitiveOrderedDict, self).__init__(*arg, **kwd) + + def _transform_key(self, key): + return key.upper() + + def __setitem__(self, key, value): + super(CaseInsensitiveOrderedDict, + self).__setitem__(self._transform_key(key), value) + + def __getitem__(self, key): + return super(CaseInsensitiveOrderedDict, + self).__getitem__(self._transform_key(key)) + + def __delitem__(self, key): + return super(CaseInsensitiveOrderedDict, + self).__delitem__(self._transform_key(key)) + + def __contains__(self, key): + return super(CaseInsensitiveOrderedDict, + self).__contains__(self._transform_key(key))