summaryrefslogtreecommitdiff
path: root/lib/skyline.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/skyline.py')
-rw-r--r--lib/skyline.py159
1 files changed, 143 insertions, 16 deletions
diff --git a/lib/skyline.py b/lib/skyline.py
index 2cc70c1..8a9755f 100644
--- a/lib/skyline.py
+++ b/lib/skyline.py
@@ -91,13 +91,14 @@ from copy import copy, deepcopy
# THIRD-PARTY
import pyfits
from stwcs import wcsutil
+from stwcs.distortion.utils import output_wcs
# LOCAL
from .polygon import SphericalPolygon
__all__ = ['SkyLine']
-__version__ = '0.2a'
-__vdate__ = '12-Jun-2012'
+__version__ = '0.3a'
+__vdate__ = '20-Jun-2012'
class SkyLineMember(object):
@@ -111,9 +112,6 @@ class SkyLineMember(object):
Parameters
----------
- self: obj
- SkyLineMember instance.
-
fname: str
FITS image.
@@ -123,12 +121,12 @@ class SkyLineMember(object):
"""
self._fname = fname
self._ext = ext
- self._polygon = SphericalPolygon.from_wcs(
- wcsutil.HSTWCS(fname, ext=ext))
+ self._wcs = wcsutil.HSTWCS(fname, ext=ext)
+ self._polygon = SphericalPolygon.from_wcs(self.wcs)
def __repr__(self):
- return 'SkyLineMember(%r, %r, %r)' % (self.fname, self.ext,
- self.polygon)
+ return '%s(%r, %r, %r, %r)' % (self.__class__.__name__, self.fname,
+ self.ext, self.wcs, self.polygon)
@property
def fname(self):
@@ -139,6 +137,10 @@ class SkyLineMember(object):
return self._ext
@property
+ def wcs(self):
+ return self._wcs
+
+ @property
def polygon(self):
return self._polygon
@@ -150,9 +152,6 @@ class SkyLine(object):
Parameters
----------
- self: obj
- `SkyLine` instance.
-
fname: str
FITS image. `None` to create empty `SkyLine`.
@@ -174,7 +173,8 @@ class SkyLine(object):
# Put mosaic of all the chips in SkyLine
if len(self.members) > 0:
- self.polygon = SphericalPolygon.multi_union([m.polygon for m in self.members])
+ self.polygon = SphericalPolygon.multi_union(
+ [m.polygon for m in self.members])
else:
self.polygon = SphericalPolygon([])
@@ -183,8 +183,8 @@ class SkyLine(object):
if what in ('from_radec', 'from_cone', 'from_wcs',
'multi_union', 'multi_intersection',
'_find_new_inside',):
- raise AttributeError('\'SkyLine\' object has no attribute \'%s\'' %
- what)
+ raise AttributeError('\'%s\' object has no attribute \'%s\'' %
+ (self.__class__.__name__, what))
else:
return getattr(self.polygon, what)
@@ -192,7 +192,8 @@ class SkyLine(object):
return deepcopy(self)
def __repr__(self):
- return 'SkyLine(%r, %r)' % (self.polygon, self.members)
+ return '%s(%r, %r)' % (self.__class__.__name__,
+ self.polygon, self.members)
@property
def polygon(self):
@@ -223,6 +224,14 @@ class SkyLine(object):
if v not in self._members:
self._members.append(v)
+ def to_wcs(self):
+ """
+ Combine WCS objects from all `members` and return a
+ new WCS object.
+
+ """
+ return output_wcs([m.wcs for m in self.members])
+
def _find_members(self, given_members):
"""
Find `SkyLineMember` in *given_members* that is in
@@ -288,3 +297,121 @@ class SkyLine(object):
newcls.polygon = self.intersection(other)
newcls.members = newcls._find_members(self.members + other.members)
return newcls
+
+ def find_max_overlap(self, skylines):
+ """
+ Find `SkyLine` from a list of *skylines* that overlaps
+ the most with *self*.
+
+ Parameters
+ ----------
+ skylines: list
+ A list of `SkyLine` instances.
+
+ Returns
+ -------
+ max_skyline: `SkyLine` instance or `None`
+ `SkyLine` that overlaps the most or `None` if no
+ overlap found.
+
+ max_overlap_area: float
+ Area of intersection.
+
+ """
+ max_skyline = None
+ max_overlap_area = 0.0
+
+ for next_s in skylines:
+ overlap_area = self.intersection(next_s).area()
+
+ if overlap_area > max_overlap_area:
+ max_overlap_area = overlap_area
+ max_skyline = next_s
+
+ return max_skyline, max_overlap_area
+
+ @staticmethod
+ def max_overlap_pair(skylines):
+ """
+ Find a pair of skylines with maximum overlap.
+
+ Parameters
+ ----------
+ skylines: list
+ A list of `SkyLine` instances.
+
+ Returns
+ -------
+ max_pair: tuple
+ Pair of `SkyLine` instances with max overlap
+ among given *skylines*. If no overlap found,
+ return `None`.
+
+ """
+ max_pair = None
+ max_overlap_area = 0.0
+
+ for i in xrange(len(skylines) - 1):
+ curr_s = skylines[i]
+ next_s, i_area = curr_s.find_max_overlap(skylines[i+1:])
+
+ if i_area > max_overlap_area:
+ max_overlap_area = i_area
+ max_pair = (curr_s, next_s)
+
+ return max_pair
+
+ @classmethod
+ def mosaic(cls, skylines):
+ """
+ Mosaic all overlapping *skylines*.
+
+ Parameters
+ ----------
+ skylines: list
+ A list of `SkyLine` instances.
+
+ Returns
+ -------
+ mosaic: `SkyLine` instance or `None`
+ Union of all overlapping *skylines*, or `None` if
+ no overlap found.
+
+ included: list
+ List of image names added to `mosaic` in the order
+ of addition.
+
+ excluded: list
+ List of image names excluded because they do not
+ overlap with `mosaic`.
+
+ """
+ out_order = []
+ excluded = []
+
+ starting_pair = cls.max_overlap_pair(skylines)
+ if starting_pair is None:
+ return starting_pair, out_order, excluded
+
+ remaining = list(skylines)
+
+ s1, s2 = starting_pair
+ mosaic = s1.add_image(s2)
+ out_order = [s1.members[0].fname, s2.members[0].fname]
+ remaining.remove(s1)
+ remaining.remove(s2)
+
+ while len(remaining) > 0:
+ next_skyline, i_area = mosaic.find_max_overlap(remaining)
+
+ if next_skyline is None:
+ for r in remaining:
+ excluded.append(r.members[0].fname)
+ break
+
+ new_mos = mosaic.add_image(next_skyline)
+ mosaic = new_mos
+ out_order.append(next_skyline.members[0].fname)
+ remaining.remove(next_skyline)
+
+ return mosaic, out_order, excluded