From 1980881927671773de80051ea78b79bdac61a484 Mon Sep 17 00:00:00 2001 From: Adeel Ahmad Date: Tue, 1 Aug 2017 16:03:48 +0500 Subject: [PATCH] Introduce precise drawing algorithm --- hips/draw/paint.py | 30 +++++++++++++++++------------- hips/draw/tests/test_ui.py | 22 ++++++++++++++++++---- hips/draw/ui.py | 6 ++++-- hips/tiles/tests/test_tile.py | 6 +++--- hips/tiles/tile.py | 9 +++++---- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/hips/draw/paint.py b/hips/draw/paint.py index 8114b02..7ea03b1 100644 --- a/hips/draw/paint.py +++ b/hips/draw/paint.py @@ -17,8 +17,6 @@ ] -# TODO for Adeel: add option "precise". -# Should be default "true" eventually, for now, can use "false" if it's very slow. class HipsPainter: """Paint a sky image from HiPS image tiles. @@ -34,6 +32,8 @@ class HipsPainter: HiPS survey properties tile_format : {'fits', 'jpg', 'png'} Format of HiPS tile + precise : bool + Use the precise drawing algorithm Examples -------- @@ -56,10 +56,11 @@ class HipsPainter: (1000, 2000) """ - def __init__(self, geometry: WCSGeometry, hips_survey: Union[str, HipsSurveyProperties], tile_format: str) -> None: + def __init__(self, geometry: WCSGeometry, hips_survey: Union[str, HipsSurveyProperties], tile_format: str, precise: bool = False) -> None: self.geometry = geometry self.hips_survey = HipsSurveyProperties.make(hips_survey) self.tile_format = tile_format + self.precise = precise self._tiles = None self.float_image = None self._stats: Dict[str, Any] = {} @@ -161,21 +162,23 @@ def run(self) -> np.ndarray: # Other useful info: number of tiles fetched def make_tile_list(self): - # Fetch all tiles needed parent_tiles = self.tiles - # TODO for Adeel: implement distortion correction here. - # Create new list of tiles, where some have been replaced by 4 children. # Suggestion: for now, just split once, no recursion. # Leave TODO, to discuss with Thomas next week. # See also: https://github.com/hipspy/hips/issues/92 - # For now, we just create a 1:1 copy - tiles = [] - for tile in parent_tiles: - tiles.append(tile) - - self.draw_tiles = tiles + if self.precise == True: + tiles = [] + for tile in parent_tiles: + corners = tile.meta.skycoord_corners.to_pixel(self.geometry.wcs) + if is_tile_distorted(corners): + tiles.append(tile.children) + else: + tiles.append(tile) + self.draw_tiles = [tile for children in tiles for tile in children] + else: + self.draw_tiles = parent_tiles def _make_empty_sky_image(self): shape = compute_image_shape( @@ -207,7 +210,8 @@ def plot_mpl_hips_tile_grid(self) -> None: not something end-users will call or need to know about. """ import matplotlib.pyplot as plt - for tile in self.tiles: + self.make_tile_list() + for tile in self.draw_tiles: corners = tile.meta.skycoord_corners.transform_to(self.geometry.celestial_frame) ax = plt.subplot(projection=self.geometry.wcs) opts = dict(color='red', lw=1, ) diff --git a/hips/draw/tests/test_ui.py b/hips/draw/tests/test_ui.py index 401874c..dc8238d 100644 --- a/hips/draw/tests/test_ui.py +++ b/hips/draw/tests/test_ui.py @@ -16,7 +16,8 @@ data_2=2296, data_sum=8756493140, dtype='>i2', - repr='HipsDrawResult(width=1000, height=2000, channels=2, dtype=>i2, format=fits)' + repr='HipsDrawResult(width=1000, height=2000, channels=2, dtype=>i2, format=fits)', + precise=False ), dict( file_format='jpg', @@ -26,7 +27,19 @@ data_2=[137, 116, 114], data_sum=828908873, dtype='uint8', - repr='HipsDrawResult(width=1000, height=2000, channels=3, dtype=uint8, format=jpg)' + repr='HipsDrawResult(width=1000, height=2000, channels=3, dtype=uint8, format=jpg)', + precise=False + ), + dict( + file_format='jpg', + shape=(1000, 2000, 3), + url='https://raw.githubusercontent.com/hipspy/hips-extra/master/datasets/samples/FermiColor/properties', + data_1=[139, 114, 115], + data_2=[142, 113, 110], + data_sum=825148172, + dtype='uint8', + repr='HipsDrawResult(width=1000, height=2000, channels=3, dtype=uint8, format=jpg)', + precise=True ), dict( file_format='png', @@ -36,7 +49,8 @@ data_2=[227, 217, 205, 255], data_sum=1635622838, dtype='uint8', - repr='HipsDrawResult(width=1000, height=2000, channels=3, dtype=uint8, format=png)' + repr='HipsDrawResult(width=1000, height=2000, channels=3, dtype=uint8, format=png)', + precise=False ), ] @@ -47,7 +61,7 @@ def test_make_sky_image(tmpdir, pars): hips_survey = HipsSurveyProperties.fetch(url=pars['url']) geometry = make_test_wcs_geometry() - result = make_sky_image(geometry=geometry, hips_survey=hips_survey, tile_format=pars['file_format']) + result = make_sky_image(geometry=geometry, hips_survey=hips_survey, tile_format=pars['file_format'], precise=pars['precise']) assert result.image.shape == pars['shape'] assert result.image.dtype == pars['dtype'] diff --git a/hips/draw/ui.py b/hips/draw/ui.py index 11facac..8a1db36 100644 --- a/hips/draw/ui.py +++ b/hips/draw/ui.py @@ -15,7 +15,7 @@ def make_sky_image(geometry: WCSGeometry, hips_survey: Union[str, 'HipsSurveyProperties'], - tile_format: str) -> 'HipsDrawResult': + tile_format: str, precise: bool = False) -> 'HipsDrawResult': """Make sky image: fetch tiles and draw. The example for this can be found on the :ref:`gs` page. @@ -29,13 +29,15 @@ def make_sky_image(geometry: WCSGeometry, hips_survey: Union[str, 'HipsSurveyPro tile_format : {'fits', 'jpg', 'png'} Format of HiPS tile to use (some surveys are available in several formats, so this extra argument is needed) + precise : bool + Use the precise drawing algorithm Returns ------- result : `~hips.HipsDrawResult` Result object """ - painter = HipsPainter(geometry, hips_survey, tile_format) + painter = HipsPainter(geometry, hips_survey, tile_format, precise) painter.run() return HipsDrawResult.from_painter(painter) diff --git a/hips/tiles/tests/test_tile.py b/hips/tiles/tests/test_tile.py index eeef134..c2712f7 100644 --- a/hips/tiles/tests/test_tile.py +++ b/hips/tiles/tests/test_tile.py @@ -82,7 +82,7 @@ def test_tile_path(self): child_shape=(256, 256), child_ipix=[1852, 1853, 1854, 1855], child_pix_idx=[[255], [255]], - child_pix_val=[2153, 2418, 2437, 2124], + child_pix_val=[2437, 2153, 2124, 2418], ), dict( label='jpg', @@ -99,7 +99,7 @@ def test_tile_path(self): child_shape=(256, 256, 3), child_ipix=[1852, 1853, 1854, 1855], child_pix_idx=[[255], [255]], - child_pix_val=[[[245, 214, 211]], [[137, 97, 87]], [[255, 241, 225]], [[109, 95, 86]]], + child_pix_val=[[[255, 241, 225]], [[245, 214, 211]], [[109, 95, 86]], [[137, 97, 87]]], ), dict( label='png', @@ -116,7 +116,7 @@ def test_tile_path(self): child_shape=(256, 256, 4), child_ipix=[24448, 24449, 24450, 24451], child_pix_idx=[[255], [255]], - child_pix_val=[[[17, 17, 17, 255]], [[13, 13, 13, 255]], [[15, 15, 15, 255]], [[20, 20, 20, 255]]], + child_pix_val=[[[15, 15, 15, 255]], [[17, 17, 17, 255]], [[20, 20, 20, 255]], [[13, 13, 13, 255]]], ), ] diff --git a/hips/tiles/tile.py b/hips/tiles/tile.py index eebaeb7..88ae6ca 100644 --- a/hips/tiles/tile.py +++ b/hips/tiles/tile.py @@ -231,10 +231,10 @@ def children(self) -> List['HipsTile']: """Create four children tiles from parent tile.""" w = self.data.shape[0] // 2 data = [ - self.data[0: w, 0: w], - self.data[0: w, w: w * 2], self.data[w: w * 2, 0: w], - self.data[w: w * 2, w: w * 2] + self.data[0: w, 0: w], + self.data[w: w * 2, w: w * 2], + self.data[0: w, w: w * 2] ] tiles = [] @@ -243,7 +243,8 @@ def children(self) -> List['HipsTile']: self.meta.order + 1, self.meta.ipix * 4 + idx, self.meta.file_format, - self.meta.frame + self.meta.frame, + len(data[0]) ) tile = self.from_numpy(meta, data[idx]) tiles.append(tile)