def test_create_subsets(self): self.assertEqual(TileGrid.create(4000, 3000, 500, 500, (-20., 10., 60., 70.), inv_y=True), TileGrid(4, 1, 1, 500, 375, (-20., 10., 60., 70.), inv_y=True)) self.assertEqual(TileGrid.create(4012, 3009, 500, 500, (-20., 10., 60., 70.), inv_y=True), TileGrid(2, 3, 5, 669, 301, (-20.0, 9.980059820538386, 60.03988035892323, 70.), inv_y=True)) self.assertEqual(TileGrid.create(4000, 3000, 500, 500, (170., 10., -160., 70.), inv_y=True), TileGrid(4, 1, 1, 500, 375, (170.0, 10.0, -160.0, 70.0), inv_y=True))
def create_from_image(cls, source_image: TiledImage, level_transformer: LevelTransformer, geo_extent: GeoExtent = None, **kwargs) -> 'ImagePyramid': """ Create an image pyramid build from a single, max-resolution source image of type TiledImage. The given source image will be returned for highest resolution level in the pyramid. Other level images are created from the given level_image_factory function. :param source_image: the high-resolution source image, see TiledImage interface :param level_transformer: transforms level z+1 into level z. Called like: level_images[z_index] = level_transformer(source_image, level_images[z_index+1], z_index, **kwargs) :param geo_extent: the geographical extent. :param kwargs: keyword arguments passed to the level_image_factory function :return: a new ImagePyramid instance """ if geo_extent is None: geo_extent = GLOBAL_GEO_EXTENT tile_grid = TileGrid.create(source_image.size[0], source_image.size[1], source_image.tile_size[0], source_image.tile_size[1], geo_extent) level_images = [None] * tile_grid.num_levels z_index_max = tile_grid.num_levels - 1 level_images[z_index_max] = source_image level_image = source_image for i in range(1, tile_grid.num_levels): z_index = z_index_max - i image_id = '%s/%d' % (source_image.id, z_index) level_images[z_index] = level_image = level_transformer( source_image, level_image, i, image_id=image_id, **kwargs) return ImagePyramid(tile_grid, level_images)
def _get_dataset_tile_grid(dataset: xr.Dataset, num_levels: int = None) -> TileGrid: geo_extent = get_dataset_bounds(dataset) inv_y = float(dataset.lat[0]) < float(dataset.lat[-1]) width, height, tile_width, tile_height = _get_cube_spatial_sizes(dataset) if num_levels is not None and tile_width is not None and tile_height is not None: width_0 = width height_0 = height for i in range(num_levels): width_0 = (width_0 + 1) // 2 height_0 = (height_0 + 1) // 2 num_level_zero_tiles_x = (width_0 + tile_width - 1) // tile_width num_level_zero_tiles_y = (height_0 + tile_height - 1) // tile_height tile_grid = TileGrid(num_levels, num_level_zero_tiles_x, num_level_zero_tiles_y, tile_width, tile_height, geo_extent, inv_y) else: try: tile_grid = TileGrid.create(width, height, tile_width, tile_height, geo_extent, inv_y) except ValueError: num_levels = 1 num_level_zero_tiles_x = 1 num_level_zero_tiles_y = 1 tile_grid = TileGrid(num_levels, num_level_zero_tiles_x, num_level_zero_tiles_y, width, height, geo_extent, inv_y) return tile_grid
def test_create_cci_ecv(self): # 72, 8, 85, 17 # Soilmoisture CCI - daily L3S self.assertEqual(TileGrid.create(1440, 720, 500, 500, GLOBAL_GEO_EXTENT, inv_y=False), TileGrid(2, 2, 1, 360, 360, GLOBAL_GEO_EXTENT, inv_y=False)) # Aerosol CCI - monthly self.assertEqual(TileGrid.create(7200, 3600, 500, 500, GLOBAL_GEO_EXTENT, inv_y=False), TileGrid(4, 2, 1, 450, 450, GLOBAL_GEO_EXTENT, inv_y=False)) # Cloud CCI - monthly self.assertEqual(TileGrid.create(720, 360, 500, 500, GLOBAL_GEO_EXTENT, inv_y=True), TileGrid(1, 2, 1, 360, 360, GLOBAL_GEO_EXTENT, inv_y=True)) # SST CCI - daily L4 self.assertEqual(TileGrid.create(8640, 4320, 500, 500, GLOBAL_GEO_EXTENT, inv_y=True), TileGrid(4, 2, 1, 540, 540, GLOBAL_GEO_EXTENT, inv_y=True)) # Land Cover CCI self.assertEqual(TileGrid.create(129600, 64800, 500, 500, GLOBAL_GEO_EXTENT, inv_y=False), TileGrid(6, 6, 3, 675, 675, GLOBAL_GEO_EXTENT, inv_y=False))
def get_dataset_tile_grid(dataset: xr.Dataset, num_levels: int = None) -> TileGrid: """ Compute the tile grid for the given *dataset* and an optional number of resolution levels *num_levels*, if given. :param dataset: The dataset. :param num_levels: The number of resolution levels. :return: A TileGrid object """ geo_extent = get_dataset_bounds(dataset) inv_y = float(dataset.lat[0]) < float(dataset.lat[-1]) width, height, tile_width, tile_height = _get_cube_spatial_sizes(dataset) if num_levels is not None and tile_width is not None and tile_height is not None: width_0 = width height_0 = height for i in range(num_levels - 1): width_0 = (width_0 + 1) // 2 height_0 = (height_0 + 1) // 2 num_level_zero_tiles_x = (width_0 + tile_width - 1) // tile_width num_level_zero_tiles_y = (height_0 + tile_height - 1) // tile_height tile_grid = TileGrid(num_levels, num_level_zero_tiles_x, num_level_zero_tiles_y, tile_width, tile_height, geo_extent, inv_y) else: try: tile_grid = TileGrid.create(width, height, tile_width, tile_height, geo_extent, inv_y) except ValueError: num_levels = 1 num_level_zero_tiles_x = 1 num_level_zero_tiles_y = 1 tile_grid = TileGrid(num_levels, num_level_zero_tiles_x, num_level_zero_tiles_y, width, height, geo_extent, inv_y) if tile_width is not None and tile_width != tile_grid.tile_width: warnings.warn( f'FIXME: wanted tile_width={tile_width} as of chunking, but will use {tile_grid.tile_width}. ' f'This is inefficient.') if tile_height is not None and tile_height != tile_grid.tile_height: warnings.warn( f'FIXME: wanted tile_height={tile_width} as of chunking, but will use {tile_grid.tile_height}. ' f'This is inefficient.') return tile_grid
def test_create_illegal_geo_extent(self): # legal - explains why the next must fail self.assertEqual(TileGrid.create(50, 25, 5, 5, (0.0, 77.5, 25.0, 90.0), inv_y=True), TileGrid(2, 5, 2, 5, 7, (0.0, 76.0, 25.0, 90.0), inv_y=True)) with self.assertRaises(ValueError): TileGrid.create(50, 25, 5, 5, (0.0, 77.5, 25.0, 90.0), inv_y=False) # legal - explains why the next must fail self.assertEqual(TileGrid.create(50, 25, 5, 5, (0., -90.0, 25., -77.5), inv_y=False), TileGrid(2, 5, 2, 5, 7, (0.0, -90.0, 25.0, -76.0), inv_y=False)) with self.assertRaises(ValueError): TileGrid.create(50, 25, 5, 5, (0., -90.0, 25., -77.5), inv_y=True)
def test_create_cci_ecv_subsets(self): # Soilmoisture CCI - daily L3S - use case #6 self.assertEqual(TileGrid.create(52, 36, 500, 500, (72, 8, 85, 17)), TileGrid(1, 1, 1, 52, 36, (72., 8., 85., 17.)))