Skip to content

Commit

Permalink
Merge pull request #293
Browse files Browse the repository at this point in the history
Image refactor
  • Loading branch information
thusser authored Nov 11, 2023
2 parents 782b916 + 1d505ce commit 6a60b2b
Show file tree
Hide file tree
Showing 12 changed files with 679 additions and 46 deletions.
141 changes: 113 additions & 28 deletions poetry.lock

Large diffs are not rendered by default.

30 changes: 12 additions & 18 deletions pyobs/images/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,8 @@ def from_file(cls, filename: str) -> Image:
New image.
"""

# open file
data = fits.open(filename, memmap=False, lazy_load_hdus=False)

# load image
image = cls._from_hdu_list(data)

# close file
data.close()
return image
with fits.open(filename, memmap=False, lazy_load_hdus=False) as data:
return cls._from_hdu_list(data)

@classmethod
def from_ccddata(cls, data: CCDData) -> Image:
Expand All @@ -113,7 +106,7 @@ def from_ccddata(cls, data: CCDData) -> Image:
image = Image(
data=data.data.astype(np.float32),
header=data.header,
mask=None if data.mask is None else data.mask,
mask=data.mask,
uncertainty=None if data.uncertainty is None else data.uncertainty.array.astype(np.float32),
)
return image
Expand All @@ -135,10 +128,8 @@ def _from_hdu_list(cls, data: fits.HDUList) -> "Image":
# find HDU with image data
for hdu in data:
if (
isinstance(hdu, fits.PrimaryHDU)
and hdu.header["NAXIS"] > 0
or isinstance(hdu, fits.ImageHDU)
and hdu.name == "SCI"
isinstance(hdu, fits.PrimaryHDU) and hdu.header["NAXIS"] > 0
or isinstance(hdu, fits.ImageHDU) and hdu.name == "SCI"
or isinstance(hdu, fits.CompImageHDU)
):
# found image HDU
Expand Down Expand Up @@ -173,7 +164,10 @@ def _from_hdu_list(cls, data: fits.HDUList) -> "Image":
@property
def unit(self) -> str:
"""Returns units of pixels in image."""
return str(self.header["BUNIT"]).lower() if "BUNIT" in self.header else "adu"
if "BUNIT" in self.header:
return str(self.header["BUNIT"]).lower()
else:
return "adu"

def __deepcopy__(self) -> Image:
"""Returns a shallow copy of this image."""
Expand All @@ -191,7 +185,7 @@ def copy(self) -> Image:
meta=self.meta,
)

def __truediv__(self, other: "Image") -> "Image":
def __truediv__(self, other: Image) -> Image:
"""Divides this image by other."""
img = self.copy()
if img.data is None or other.data is None:
Expand Down Expand Up @@ -251,8 +245,8 @@ def write_catalog(self, f: Any, *args: Any, **kwargs: Any) -> None:
if self.catalog is None:
return

# create HDU and write it
table_to_hdu(self.catalog).writeto(f, *args, **kwargs)
hdu = table_to_hdu(self.catalog)
hdu.writeto(f, *args, **kwargs)

def to_ccddata(self) -> CCDData:
"""Convert Image to CCDData"""
Expand Down
1 change: 1 addition & 0 deletions pyobs/images/meta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from .radecoffsets import RaDecOffsets
from .skyoffsets import SkyOffsets
from .onskydistance import OnSkyDistance
from .exptime import ExpTime
Empty file added tests/images/__init__.py
Empty file.
Empty file added tests/images/meta/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions tests/images/meta/test_altazoffsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from pyobs.images.meta import AltAzOffsets


def test_alt_az_offsets():
dalt = 1.0
daz = 2.0

meta = AltAzOffsets(dalt, daz)

assert meta.dalt == dalt
assert meta.daz == daz
8 changes: 8 additions & 0 deletions tests/images/meta/test_exptime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pyobs.images.meta import ExpTime


def test_exp_time():
exp_time = 1.0
meta = ExpTime(exp_time)

assert meta.exptime == exp_time
10 changes: 10 additions & 0 deletions tests/images/meta/test_onskydistance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from astropy.coordinates import Angle
from pyobs.images.meta import OnSkyDistance


def test_onskydistance():
distance = Angle(1.0, unit="deg")
meta = OnSkyDistance(distance)

assert meta.distance.unit == distance.unit
assert meta.distance.value == distance.value
11 changes: 11 additions & 0 deletions tests/images/meta/test_pixeloffsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from pyobs.images.meta import PixelOffsets


def test_pixeloffsets():
dx = 1.0
dy = 2.0

meta = PixelOffsets(dx, dy)

assert meta.dx == dx
assert meta.dy == dy
12 changes: 12 additions & 0 deletions tests/images/meta/test_radecoffsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pyobs.images.meta import RaDecOffsets


def test_radecoffsets():
dra = 1.0
ddec = 2.0

meta = RaDecOffsets(dra, ddec)

assert meta.dra == dra
assert meta.ddec == ddec

86 changes: 86 additions & 0 deletions tests/images/meta/test_skyoffsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import astropy

from pyobs.images.meta import SkyOffsets
from astropy.coordinates import SkyCoord, BaseCoordinateFrame


def test_init():
coord0 = SkyCoord(ra=0.0, dec=0.0, unit="deg")
coord1 = SkyCoord(ra=1.0, dec=1.0, unit="deg")

meta = SkyOffsets(coord0, coord1)

assert meta.coord0.ra.deg == coord0.ra.deg
assert meta.coord0.dec.deg == coord0.dec.deg

assert meta.coord1.ra.deg == coord1.ra.deg
assert meta.coord1.dec.deg == coord1.dec.deg


def test_to_frame_non_value():
coord0 = SkyCoord(ra=0.0, dec=0.0, unit="deg")
coord1 = SkyCoord(ra=1.0, dec=1.0, unit="deg")

meta = SkyOffsets(coord0, coord1)

framed_coord0, framed_coord1 = meta._to_frame()

assert framed_coord0.ra.deg == coord0.ra.deg
assert framed_coord0.dec.deg == coord0.dec.deg

assert framed_coord1.ra.deg == coord1.ra.deg
assert framed_coord1.dec.deg == coord1.dec.deg


def test_to_frame_w_value(mocker):
"""
Tests that SkyCoord.transform_to is correctly used
"""
frame = BaseCoordinateFrame()

coord0 = SkyCoord(ra=0.0, dec=0.0, unit="deg")
coord1 = SkyCoord(ra=1.0, dec=1.0, unit="deg")
meta = SkyOffsets(coord0, coord1)

mocker.patch("astropy.coordinates.SkyCoord.transform_to", return_value=0)

x, y = meta._to_frame(frame)

astropy.coordinates.SkyCoord.transform_to.assert_called_with(frame)

assert x == 0
assert y == 0


def test_separation(mocker):
"""
Tests that _to_frame and separation is correctly used
"""
coord0 = SkyCoord(ra=0.0, dec=0.0, unit="deg")
coord1 = SkyCoord(ra=1.0, dec=1.0, unit="deg")
meta = SkyOffsets(coord0, coord1)

mocker.patch.object(meta, "_to_frame", return_value=(coord0, coord1))
mocker.patch("astropy.coordinates.SkyCoord.separation", return_value=0)

assert meta.separation() == 0

meta._to_frame.assert_called_once_with(None)
astropy.coordinates.SkyCoord.separation.assert_called_once_with(coord1)


def test_spherical_offsets(mocker):
"""
Tests that _to_frame and spherical_offsets_to is correctly used
"""
coord0 = SkyCoord(ra=0.0, dec=0.0, unit="deg")
coord1 = SkyCoord(ra=1.0, dec=1.0, unit="deg")
meta = SkyOffsets(coord0, coord1)

mocker.patch.object(meta, "_to_frame", return_value=(coord0, coord1))
mocker.patch("astropy.coordinates.SkyCoord.spherical_offsets_to", return_value=(0, 1))

assert meta.spherical_offsets() == (0, 1)

meta._to_frame.assert_called_once_with(None)
astropy.coordinates.SkyCoord.spherical_offsets_to.assert_called_once_with(coord1.frame)
Loading

0 comments on commit 6a60b2b

Please sign in to comment.