def test_add_int(self): arr = np.zeros((1, 4, 4)) tile = {'data': arr, 'no_data_value': -500} rdd = BaseTestClass.geopysc.pysc.parallelize([(self.spatial_key, tile)]) tiled = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, self.metadata) result = tiled + 1 actual = result.to_numpy_rdd().first()[1]['data'] self.assertTrue((actual == 1).all())
def read(geopysc, rdd_type, uri, layer_name, layer_zoom, options=None, numPartitions=None, **kwargs): """Reads a single, zoom layer from a GeoTrellis catalog. Note: This will read the entire layer. If only part of the layer is needed, use :func:`query` instead. Args: geopysc (:cls:`~geopyspark.GeoPyContext`): The ``GeoPyContext`` being used this session. rdd_type (str): What the spatial type of the geotiffs are. This is represented by the constants: ``SPATIAL`` and ``SPACETIME``. uri (str): The Uniform Resource Identifier used to point towards the desired GeoTrellis catalog to be read from. The shape of this string varies depending on backend. layer_name (str): The name of the GeoTrellis catalog to be read from. layer_zoom (int): The zoom level of the layer that is to be read. options (dict, optional): Additional parameters for reading the layer for specific backends. The dictionary is only used for ``Cassandra`` and ``HBase``, no other backend requires this to be set. numPartitions (int, optional): Sets RDD partition count when reading from catalog. **kwargs: The optional parameters can also be set as keywords arguments. The keywords must be in camel case. If both options and keywords are set, then the options will be used. Returns: :class:`~geopyspark.geotrellis.rdd.TiledRasterRDD` """ if options: options = options elif kwargs: options = kwargs else: options = {} _construct_catalog(geopysc, uri, options) cached = _mapped_cached[uri] key = geopysc.map_key_input(rdd_type, True) if numPartitions is None: numPartitions = geopysc.pysc.defaultMinPartitions srdd = cached.reader.read(key, layer_name, layer_zoom, numPartitions) return TiledRasterRDD(geopysc, rdd_type, srdd)
def test_divide_tiled_rdd(self): arr = np.array([[[5.0, 5.0, 5.0, 5.0], [5.0, 5.0, 5.0, 5.0], [5.0, 5.0, 5.0, 5.0], [5.0, 5.0, 5.0, 5.0]]], dtype=float) divider = np.array([[[1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0]]], dtype=float) tile = {'data': arr, 'no_data_value': float('nan')} tile2 = {'data': divider, 'no_data_value': float('nan')} rdd = BaseTestClass.geopysc.pysc.parallelize([(self.spatial_key, tile)]) rdd2 = BaseTestClass.geopysc.pysc.parallelize([(self.spatial_key, tile2)]) tiled = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, self.metadata) tiled2 = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd2, self.metadata) result = tiled / tiled2 actual = result.to_numpy_rdd().first()[1]['data'] self.assertTrue((actual == 5.0).all())
def test_combined_operations(self): arr = np.array([[[10, 10, 10, 10], [20, 20, 20, 20], [10, 10, 10, 10], [20, 20, 20, 20]]], dtype=int) tile = {'data': arr, 'no_data_value': -500} rdd = BaseTestClass.geopysc.pysc.parallelize([(self.spatial_key, tile)]) tiled = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, self.metadata) result = (tiled + tiled) / 2 actual = result.to_numpy_rdd().first()[1]['data'] self.assertTrue((actual == arr).all())
def test_euclideandistance(self): def mapTransform(layoutDefinition, spatialKey): ex = layoutDefinition.extent x_range = ex.xmax - ex.xmin xinc = x_range / layoutDefinition.tileLayout.layoutCols yrange = ex.ymax - ex.ymin yinc = yrange / layoutDefinition.tileLayout.layoutRows return { 'xmin': ex.xmin + xinc * spatialKey['col'], 'xmax': ex.xmin + xinc * (spatialKey['col'] + 1), 'ymin': ex.ymax - yinc * (spatialKey['row'] + 1), 'ymax': ex.ymax - yinc * spatialKey['row'] } def gridToMap(layoutDefinition, spatialKey, px, py): ex = mapTransform(layoutDefinition, spatialKey) x_range = ex['xmax'] - ex['xmin'] xinc = x_range / layoutDefinition.tileLayout.tileCols yrange = ex['ymax'] - ex['ymin'] yinc = yrange / layoutDefinition.tileLayout.tileRows return (ex['xmin'] + xinc * (px + 0.5), ex['ymax'] - yinc * (py + 0.5)) def distanceToGeom(layoutDefinition, spatialKey, geom, px, py): x, y = gridToMap(layoutDefinition, spatialKey, px, py) return geom.distance(Point(x, y)) tiled = TiledRasterRDD.euclidean_distance(BaseTestClass.geopysc, self.pts_wm, 3857, 7) result = tiled.stitch()['data'][0] arr = np.zeros((256, 256), dtype=float) it = np.nditer(arr, flags=['multi_index']) while not it.finished: py, px = it.multi_index arr[py][px] = distanceToGeom( tiled.layer_metadata.layout_definition, { 'col': 64, 'row': 63 }, self.pts_wm, px, py) it.iternext() self.assertTrue(np.all(abs(result - arr) < 1e-8))
def test_multiply_double(self): arr = np.array([[[1.0, 1.0, 1.0, 1.0], [2.0, 2.0, 2.0, 2.0], [3.0, 3.0, 3.0, 3.0], [4.0, 4.0, 4.0, 4.0]]], dtype=float) tile = {'data': arr, 'no_data_value': float('nan')} rdd = BaseTestClass.geopysc.pysc.parallelize([(self.spatial_key, tile)]) tiled = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, self.metadata) result = 5.0 * tiled actual = result.to_numpy_rdd().first()[1]['data'] expected = np.array([[[5.0, 5.0, 5.0, 5.0], [10.0, 10.0, 10.0, 10.0], [15.0, 15.0, 15.0, 15.0], [20.0, 20.0, 20.0, 20.0]]], dtype=float) self.assertTrue((actual == expected).all())
class CostDistanceTest(BaseTestClass): data = np.array([[[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 0.0]]]) layer = [({ 'row': 0, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 0, 'col': 1 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 1 }, { 'no_data_value': -1.0, 'data': data })] rdd = BaseTestClass.geopysc.pysc.parallelize(layer) extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0} layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5} metadata = { 'cellType': 'float32ud-1.0', 'extent': extent, 'crs': '+proj=longlat +datum=WGS84 +no_defs ', 'bounds': { 'minKey': { 'col': 0, 'row': 0 }, 'maxKey': { 'col': 1, 'row': 1 } }, 'layoutDefinition': { 'extent': extent, 'tileLayout': { 'tileCols': 5, 'tileRows': 5, 'layoutCols': 2, 'layoutRows': 2 } } } tiled_rdd = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, metadata) @pytest.fixture(autouse=True) def tearDown(self): yield BaseTestClass.geopysc.pysc._gateway.close() def test_polygonal_min(self): polygon = Polygon([(0.0, 0.0), (0.0, 33.0), (33.0, 33.0), (33.0, 0.0), (0.0, 0.0)]) result = self.tiled_rdd.polygonal_min(polygon, float) self.assertEqual(result, 0.0) def test_polygonal_max(self): polygon = Polygon([(1.0, 1.0), (1.0, 10.0), (10.0, 10.0), (10.0, 1.0)]) result = self.tiled_rdd.polygonal_max(polygon, float) self.assertEqual(result, 1.0) def test_polygonal_sum(self): polygon = Polygon([(0.0, 0.0), (0.0, 33.0), (33.0, 33.0), (33.0, 0.0), (0.0, 0.0)]) result = self.tiled_rdd.polygonal_sum(polygon, float) self.assertEqual(result, 96.0) def test_polygonal_mean(self): polygon = Polygon([(1.0, 1.0), (1.0, 10.0), (10.0, 10.0), (10.0, 1.0)]) result = self.tiled_rdd.polygonal_mean(polygon) self.assertEqual(result, 1.0)
class CostDistanceTest(BaseTestClass): data = np.array([[[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 0.0]]]) layer = [({ 'row': 0, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 0, 'col': 1 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 1 }, { 'no_data_value': -1.0, 'data': data })] rdd = BaseTestClass.geopysc.pysc.parallelize(layer) extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0} layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5} metadata = { 'cellType': 'float32ud-1.0', 'extent': extent, 'crs': '+proj=longlat +datum=WGS84 +no_defs ', 'bounds': { 'minKey': { 'col': 0, 'row': 0 }, 'maxKey': { 'col': 1, 'row': 1 } }, 'layoutDefinition': { 'extent': extent, 'tileLayout': { 'tileCols': 5, 'tileRows': 5, 'layoutCols': 2, 'layoutRows': 2 } } } raster_rdd = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, metadata) @pytest.fixture(autouse=True) def tearDown(self): yield BaseTestClass.geopysc.pysc._gateway.close() def test_costdistance_finite(self): def zero_one(kv): k = kv[0] return (k.col == 0 and k.row == 1) result = self.raster_rdd.cost_distance(geometries=[Point(13, 13)], max_distance=144000.0) tile = result.to_numpy_rdd().filter(zero_one).first()[1] point_distance = tile['data'][0][1][3] self.assertEqual(point_distance, 0.0) def test_costdistance_finite_int(self): def zero_one(kv): k = kv[0] return (k.col == 0 and k.row == 1) result = self.raster_rdd.cost_distance(geometries=[Point(13, 13)], max_distance=144000) tile = result.to_numpy_rdd().filter(zero_one).first()[1] point_distance = tile['data'][0][1][3] self.assertEqual(point_distance, 0.0) def test_costdistance_infinite(self): def zero_one(kv): k = kv[0] return (k.col == 0 and k.row == 1) result = self.raster_rdd.cost_distance(geometries=[Point(13, 13)], max_distance=float('inf')) tile = result.to_numpy_rdd().filter(zero_one).first()[1] point_distance = tile['data'][0][0][0] self.assertTrue(point_distance > 1250000)
class MaskTest(BaseTestClass): geopysc = BaseTestClass.geopysc data = np.array([[[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0]]]) layer = [({ 'row': 0, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 0, 'col': 1 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 1 }, { 'no_data_value': -1.0, 'data': data })] rdd = geopysc.pysc.parallelize(layer) extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0} layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5} metadata = { 'cellType': 'float32ud-1.0', 'extent': extent, 'crs': '+proj=longlat +datum=WGS84 +no_defs ', 'bounds': { 'minKey': { 'col': 0, 'row': 0 }, 'maxKey': { 'col': 1, 'row': 1 } }, 'layoutDefinition': { 'extent': extent, 'tileLayout': layout } } geometries = Polygon([(17, 17), (42, 17), (42, 42), (17, 42)]) raster_rdd = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, metadata) @pytest.fixture(autouse=True) def tearDown(self): yield BaseTestClass.geopysc.pysc._gateway.close() def test_geotrellis_mask(self): result = self.raster_rdd.mask( geometries=self.geometries).to_numpy_rdd() n = result.map(lambda kv: np.sum(kv[1]['data'])).reduce( lambda a, b: a + b) self.assertEqual(n, 25.0)
class FocalTest(BaseTestClass): data = np.array([[[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 0.0]]]) ''' layer = [({'row': 0, 'col': 0}, {'no_data_value': -1.0, 'data': data}), ({'row': 1, 'col': 0}, {'no_data_value': -1.0, 'data': data}), ({'row': 0, 'col': 1}, {'no_data_value': -1.0, 'data': data}), ({'row': 1, 'col': 1}, {'no_data_value': -1.0, 'data': data})] ''' layer = [(SpatialKey(0, 0), { 'no_data_value': -1.0, 'data': data }), (SpatialKey(0, 1), { 'no_data_value': -1.0, 'data': data }), (SpatialKey(1, 0), { 'no_data_value': -1.0, 'data': data }), (SpatialKey(1, 1), { 'no_data_value': -1.0, 'data': data })] rdd = BaseTestClass.geopysc.pysc.parallelize(layer) extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0} layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5} metadata = { 'cellType': 'float32ud-1.0', 'extent': extent, 'crs': '+proj=longlat +datum=WGS84 +no_defs ', 'bounds': { 'minKey': { 'col': 0, 'row': 0 }, 'maxKey': { 'col': 1, 'row': 1 } }, 'layoutDefinition': { 'extent': extent, 'tileLayout': { 'tileCols': 5, 'tileRows': 5, 'layoutCols': 2, 'layoutRows': 2 } } } raster_rdd = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, metadata) @pytest.fixture(autouse=True) def tearDown(self): yield BaseTestClass.geopysc.pysc._gateway.close() def test_focal_sum(self): result = self.raster_rdd.focal(operation=SUM, neighborhood=SQUARE, param_1=1.0) self.assertTrue(result.to_numpy_rdd().first()[1]['data'][0][1][0] >= 6) def test_focal_sum_int(self): result = self.raster_rdd.focal(operation=SUM, neighborhood=SQUARE, param_1=1) self.assertTrue(result.to_numpy_rdd().first()[1]['data'][0][1][0] >= 6) def test_focal_sum_square(self): square = Square(extent=1.0) result = self.raster_rdd.focal(operation=SUM, neighborhood=square) self.assertTrue(result.to_numpy_rdd().first()[1]['data'][0][1][0] >= 6) def test_focal_min(self): result = self.raster_rdd.focal(operation=MIN, neighborhood=ANNULUS, param_1=2.0, param_2=1.0) self.assertEqual(result.to_numpy_rdd().first()[1]['data'][0][0][0], -1) def test_focal_min_annulus(self): annulus = Annulus(inner_radius=2.0, outer_radius=1.0) result = self.raster_rdd.focal(operation=MIN, neighborhood=annulus) self.assertEqual(result.to_numpy_rdd().first()[1]['data'][0][0][0], -1) def test_focal_min_int(self): result = self.raster_rdd.focal(operation=MIN, neighborhood=ANNULUS, param_1=2, param_2=1) self.assertEqual(result.to_numpy_rdd().first()[1]['data'][0][0][0], -1)
class LookupTest(BaseTestClass): data = np.array([[[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 0.0]]]) layer = [({ 'row': 0, 'col': 0 }, { 'no_data_value': -1.0, 'data': data + 0 }), ({ 'row': 1, 'col': 0 }, { 'no_data_value': -1.0, 'data': data + 1 }), ({ 'row': 0, 'col': 1 }, { 'no_data_value': -1.0, 'data': data + 2 }), ({ 'row': 1, 'col': 1 }, { 'no_data_value': -1.0, 'data': data + 3 })] rdd = BaseTestClass.geopysc.pysc.parallelize(layer) extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0} layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5} metadata = { 'cellType': 'float32ud-1.0', 'extent': extent, 'crs': '+proj=longlat +datum=WGS84 +no_defs ', 'bounds': { 'minKey': { 'col': 0, 'row': 0 }, 'maxKey': { 'col': 1, 'row': 1 } }, 'layoutDefinition': { 'extent': extent, 'tileLayout': { 'tileCols': 5, 'tileRows': 5, 'layoutCols': 2, 'layoutRows': 2 } } } raster_rdd = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, metadata) @pytest.fixture(autouse=True) def tearDown(self): yield BaseTestClass.geopysc.pysc._gateway.close() def test_lookup_1(self): result = self.raster_rdd.lookup(0, 0)[0] n = np.sum(result['data']) self.assertEqual(n, 24 + 0 * 25) def test_lookup_2(self): result = self.raster_rdd.lookup(0, 1)[0] n = np.sum(result['data']) self.assertEqual(n, 24 + 1 * 25) def test_lookup_3(self): result = self.raster_rdd.lookup(1, 0)[0] n = np.sum(result['data']) self.assertEqual(n, 24 + 2 * 25) def test_lookup_4(self): result = self.raster_rdd.lookup(1, 1)[0] n = np.sum(result['data']) self.assertEqual(n, 24 + 3 * 25) def test_lookup_5(self): with pytest.raises(IndexError): result = self.raster_rdd.lookup(13, 33)
def query(geopysc, rdd_type, uri, layer_name, layer_zoom, intersects, time_intervals=None, proj_query=None, options=None, numPartitions=None, **kwargs): """Queries a single, zoom layer from a GeoTrellis catalog given spatial and/or time parameters. Unlike read, this method will only return part of the layer that intersects the specified region. Note: The whole layer could still be read in if ``intersects`` and/or ``time_intervals`` have not been set, or if the querried region contains the entire layer. Args: geopysc (:cls:`~geopyspark.GeoPyContext`): The ``GeoPyContext`` being used this session. rdd_type (str): What the spatial type of the geotiffs are. This is represented by the constants: ``SPATIAL`` and ``SPACETIME``. Note: All of the GeoTiffs must have the same saptial type. uri (str): The Uniform Resource Identifier used to point towards the desired GeoTrellis catalog to be read from. The shape of this string varies depending on backend. layer_name (str): The name of the GeoTrellis catalog to be querried. layer_zoom (int): The zoom level of the layer that is to be querried. intersects (str or Polygon or :class:`~geopyspark.geotrellis.data_structures.Extent`): The desired spatial area to be returned. Can either be a string, a shapely Polygon, or an instance of ``Extent``. If the value is a string, it must be the WKT string, geometry format. The types of Polygons supported: * Point * Polygon * MultiPolygon Note: Only layers that were made from spatial, singleband GeoTiffs can query a Point. All other types are restricted to Polygon and MulitPolygon. time_intervals (list, optional): A list of strings that time intervals to query. The strings must be in a valid date-time format. This parameter is only used when querying spatial-temporal data. The default value is, None. If None, then only the spatial area will be querried. options (dict, optional): Additional parameters for querying the tile for specific backends. The dictioanry is only used for ``Cassandra`` and ``HBase``, no other backend requires this to be set. numPartitions (int, optional): Sets RDD partition count when reading from catalog. **kwargs: The optional parameters can also be set as keywords arguements. The keywords must be in camel case. If both options and keywords are set, then the options will be used. Returns: :class:`~geopyspark.geotrellis.rdd.TiledRasterRDD` """ if options: options = options elif kwargs: options = kwargs else: options = {} _construct_catalog(geopysc, uri, options) cached = _mapped_cached[uri] key = geopysc.map_key_input(rdd_type, True) if time_intervals is None: time_intervals = [] if proj_query is None: proj_query = "" if isinstance(proj_query, int): proj_query = "EPSG:" + str(proj_query) if numPartitions is None: numPartitions = geopysc.pysc.defaultMinPartitions if isinstance(intersects, Polygon) or isinstance(intersects, MultiPolygon) \ or isinstance(intersects, Point): srdd = cached.reader.query(key, layer_name, layer_zoom, dumps(intersects), time_intervals, proj_query, numPartitions) elif isinstance(intersects, Extent): srdd = cached.reader.query(key, layer_name, layer_zoom, dumps(intersects.to_poly), time_intervals, proj_query, numPartitions) elif isinstance(intersects, str): srdd = cached.reader.query(key, layer_name, layer_zoom, intersects, time_intervals, proj_query) else: raise TypeError("Could not query intersection", intersects) return TiledRasterRDD(geopysc, rdd_type, srdd)
class StitchTest(BaseTestClass): data = np.array([[[1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 0.0]]]) layer = [({ 'row': 0, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 0 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 0, 'col': 1 }, { 'no_data_value': -1.0, 'data': data }), ({ 'row': 1, 'col': 1 }, { 'no_data_value': -1.0, 'data': data })] rdd = BaseTestClass.geopysc.pysc.parallelize(layer) extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0} layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5} metadata = { 'cellType': 'float32ud-1.0', 'extent': extent, 'crs': '+proj=longlat +datum=WGS84 +no_defs ', 'bounds': { 'minKey': { 'col': 0, 'row': 0 }, 'maxKey': { 'col': 1, 'row': 1 } }, 'layoutDefinition': { 'extent': extent, 'tileLayout': { 'tileCols': 5, 'tileRows': 5, 'layoutCols': 2, 'layoutRows': 2 } } } raster_rdd = TiledRasterRDD.from_numpy_rdd(BaseTestClass.geopysc, SPATIAL, rdd, metadata) @pytest.fixture(scope='class', autouse=True) def tearDown(self): yield BaseTestClass.geopysc.pysc._gateway.close() def test_stitch(self): result = self.raster_rdd.stitch() self.assertTrue(result['data'].shape == (1, 10, 10))