def test_reproject_dst_crs_none(): with pytest.raises(CRSError): reproject(np.ones((2, 2)), np.zeros((2, 2)), src_transform=Affine.identity(), dst_transform=Affine.identity(), src_crs=WGS84_crs)
def test_inverse(self): seq_almost_equal(~Affine.identity(), Affine.identity()) seq_almost_equal( ~Affine.translation(2, -3), Affine.translation(-2, 3)) seq_almost_equal( ~Affine.rotation(-33.3), Affine.rotation(33.3)) t = Affine(1, 2, 3, 4, 5, 6) seq_almost_equal(~t * t, Affine.identity())
def test_reproject_dst_crs_none(): with pytest.raises(CRSError): reproject( np.ones((2, 2)), np.zeros((2, 2)), src_transform=Affine.identity(), dst_transform=Affine.identity(), src_crs=WGS84_crs, )
def test_almost_equals_2(self): EPSILON = 1e-10 E = EPSILON * 0.5 t = Affine(1.0, E, 0, -E, 1.0 + E, E) assert t.almost_equals(Affine.identity(), precision=EPSILON) assert Affine.identity().almost_equals(t, precision=EPSILON) assert t.almost_equals(t, precision=EPSILON) t = Affine(1.0, 0, 0, -EPSILON, 1.0, 0) assert not t.almost_equals(Affine.identity(), precision=EPSILON) assert not Affine.identity().almost_equals(t, precision=EPSILON) assert t.almost_equals(t, precision=EPSILON)
def test_almost_equals(self): EPSILON = 1e-5 E = EPSILON * 0.5 t = Affine(1.0, E, 0, -E, 1.0 + E, E) assert t.almost_equals(Affine.identity()) assert Affine.identity().almost_equals(t) assert t.almost_equals(t) t = Affine(1.0, 0, 0, -EPSILON, 1.0, 0) assert not t.almost_equals(Affine.identity()) assert not Affine.identity().almost_equals(t) assert t.almost_equals(t)
def test_almost_equals(self): from affine import EPSILON assert EPSILON != 0, EPSILON E = EPSILON * 0.5 t = Affine(1.0, E, 0, -E, 1.0 + E, E) assert t.almost_equals(Affine.identity()) assert Affine.identity().almost_equals(t) assert t.almost_equals(t) t = Affine(1.0, 0, 0, -EPSILON, 1.0, 0) assert not t.almost_equals(Affine.identity()) assert not Affine.identity().almost_equals(t) assert t.almost_equals(t)
def transformPoint(angleB, massA_x, massA_y, massB_x, massB_y): ''' transform the origin of the space so that the mass center of animalB is the origin of the new space ''' Affine.identity() x = massA_x - massB_x y = massA_y - massB_y rotation = Affine.rotation(90- math.degrees( angleB ) ) * ( x , y ) return rotation[0], rotation[1]
def test_xy_rowcol_inverse(): # TODO this is an ideal candiate for # property-based testing with hypothesis aff = Affine.identity() rows_cols = ([0, 0, 10, 10], [0, 10, 0, 10]) assert rows_cols == rowcol(aff, *xy(aff, *rows_cols))
def test_scale_constructor(self): scale = Affine.scale(5) assert isinstance(scale, Affine) assert_equal(tuple(scale), (5, 0, 0, 0, 5, 0, 0, 0, 1)) scale = Affine.scale(-1, 2) assert_equal(tuple(scale), (-1, 0, 0, 0, 2, 0, 0, 0, 1)) assert_equal(tuple(Affine.scale(1)), tuple(Affine.identity()))
def test_geometry_mask_invert(basic_geometry, basic_image_2x2): assert np.array_equal( basic_image_2x2, geometry_mask([basic_geometry], out_shape=DEFAULT_SHAPE, transform=Affine.identity(), invert=True))
def test_is_rectilinear(self): assert Affine.identity().is_rectilinear assert Affine.scale(2.5, 6.1).is_rectilinear assert Affine.translation(4, -1).is_rectilinear assert Affine.rotation(90).is_rectilinear assert not Affine.shear(4, -1).is_rectilinear assert not Affine.rotation(-26).is_rectilinear
def __init__(self, value, nodata, shape=(2, 2), *args, **kwargs): self.value = value self.crs = epsg4326 self.transform = Affine.identity() self.dtype = np.int16 if not np.isnan(nodata) else np.float64 self.shape = shape self.nodata = nodata
def pixelated_image_file(tmpdir, pixelated_image): """ A basic raster file with a 10x10 array for testing sieve functions. Contains data from pixelated_image. Returns ------- string Filename of test raster file """ from affine import Affine import rasterio image = pixelated_image outfilename = str(tmpdir.join('pixelated_image.tif')) kwargs = { "crs": CRS({'init': 'epsg:4326'}), "transform": Affine.identity(), "count": 1, "dtype": rasterio.uint8, "driver": "GTiff", "width": image.shape[1], "height": image.shape[0], "nodata": 255 } with rasterio.open(outfilename, 'w', **kwargs) as out: out.write(image, indexes=1) return outfilename
def test_is_conformal(self): assert Affine.identity().is_conformal assert Affine.scale(2.5, 6.1).is_conformal assert Affine.translation(4, -1).is_conformal assert Affine.rotation(90).is_conformal assert Affine.rotation(-26).is_conformal assert not Affine.shear(4, -1).is_conformal
def _write_polygon(geobox, polygon, zoom_fill): geobox_ext = geobox.extent if geobox_ext.within(polygon): data = numpy.full([geobox.height, geobox.width], fill_value=1, dtype="uint8") else: data = numpy.zeros([geobox.height, geobox.width], dtype="uint8") if polygon.type == 'Polygon': coordinates_list = [polygon.json["coordinates"]] elif polygon.type == 'MultiPolygon': coordinates_list = polygon.json["coordinates"] else: raise Exception("Unexpected extent/geobox polygon geometry type: %s" % polygon.type) for polygon_coords in coordinates_list: pixel_coords = [~geobox.transform * coords for coords in polygon_coords[0]] rs, cs = skimg_polygon([c[1] for c in pixel_coords], [c[0] for c in pixel_coords], shape=[geobox.width, geobox.height]) data[rs, cs] = 1 with MemoryFile() as memfile: with memfile.open(driver='PNG', width=geobox.width, height=geobox.height, count=len(zoom_fill), transform=Affine.identity(), nodata=0, dtype='uint8') as thing: for idx, fill in enumerate(zoom_fill, start=1): thing.write_band(idx, data * fill) return memfile.read()
def _write_polygon(geobox, polygon, zoom_fill): geobox_ext = geobox.extent if geobox_ext.within(polygon): data = numpy.full([geobox.width, geobox.height], fill_value=1, dtype="uint8") else: data = numpy.zeros([geobox.width, geobox.height], dtype="uint8") if not geobox_ext.disjoint(polygon): intersection = geobox_ext.intersection(polygon) crs_coords = intersection.json["coordinates"][0] pixel_coords = [ ~geobox.transform * coords for coords in crs_coords ] rs, cs = skimg_polygon( [int_trim(c[1], 0, geobox.height - 1) for c in pixel_coords], [int_trim(c[0], 0, geobox.width - 1) for c in pixel_coords]) data[rs, cs] = 1 with MemoryFile() as memfile: with memfile.open(driver='PNG', width=geobox.width, height=geobox.height, count=len(zoom_fill), transform=Affine.identity(), nodata=0, dtype='uint8') as thing: for idx, fill in enumerate(zoom_fill, start=1): thing.write_band(idx, data * fill) return memfile.read()
def test_rotation_angle(): assert Affine.identity().rotation_angle == 0.0 assert Affine.scale(2).rotation_angle == 0.0 assert Affine.scale(2, 1).rotation_angle == 0.0 assert Affine.translation(32, -47).rotation_angle == pytest.approx(0.0) assert Affine.rotation(30).rotation_angle == pytest.approx(30) assert Affine.rotation(-150).rotation_angle == pytest.approx(-150)
def transform(self, recalc=False): """ Parameters ---------- recalc: bool, optional If True, it will re-calculate the transform instead of using the cached transform. Returns ------- :obj:`affine.Afffine`: The affine of the :obj:`xarray.Dataset` | :obj:`xarray.DataArray` """ transform = self._cached_transform() if transform and not transform.is_rectilinear: if recalc: warnings.warn("Non-rectilinear transform found. Unable to recalculate.") return transform try: src_left, _, _, src_top = self.bounds(recalc=recalc) src_resolution_x, src_resolution_y = self.resolution(recalc=recalc) except (DimensionMissingCoordinateError, DimensionError): return Affine.identity() return Affine.translation(src_left, src_top) * Affine.scale( src_resolution_x, src_resolution_y )
def test_geometry_mask(basic_geometry, basic_image_2x2): with rasterio.Env(): assert np.array_equal( basic_image_2x2 == 0, geometry_mask([basic_geometry], out_shape=DEFAULT_SHAPE, transform=Affine.identity()))
def test_scale_constructor(self): scale = Affine.scale(5) assert isinstance(scale, Affine) assert_equal(tuple(scale), (5,0,0, 0,5,0, 0,0,1)) scale = Affine.scale(-1, 2) assert_equal(tuple(scale), (-1,0,0, 0,2,0, 0,0,1)) assert_equal(tuple(Affine.scale(1)), tuple(Affine.identity()))
def test_mul_fallback_unpack(): """Support fallback in case that other is a single object.""" class TextPoint: """Not iterable, will trigger ValueError in Affine.__mul__.""" def __rmul__(self, other): return other * (1, 2) assert Affine.identity() * TextPoint() == (1, 2)
def __init__(self, value, *args, **kwargs): self.value = value self.crs = geometry.CRS('EPSG:4326') self.transform = Affine.identity() self.dtype = np.dtype('int16') self.shape = (2, 2) self.nodata = -999
def test_constructor(self): """ verify all construction methods are identical. """ h_from_ndarray = Homography([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) h_from_affine = Homography(Affine.identity()) h_from_homography = Homography(h_from_ndarray) self.assertEqual(h_from_ndarray, h_from_affine) self.assertEqual(h_from_ndarray, h_from_homography) self.assertEqual(h_from_ndarray, Homography.identity())
def test_geometry_mask(basic_geometry, basic_image_2x2): assert np.array_equal( basic_image_2x2 == 0, geometry_mask( [basic_geometry], out_shape=DEFAULT_SHAPE, transform=Affine.identity() ) )
def test_geometry_invalid_geom(geom): """An invalid geometry should fail""" with pytest.raises(ValueError) as exc_info, pytest.warns(ShapeSkipWarning): geometry_mask([geom], out_shape=DEFAULT_SHAPE, transform=Affine.identity()) assert 'No valid geometry objects found for rasterize' in exc_info.value.args[ 0]
def test_identity_constructor(self): ident = Affine.identity() assert isinstance(ident, Affine) assert_equal( tuple(ident), (1, 0, 0, 0, 1, 0, 0, 0, 1)) assert ident.is_identity
def test_identity_constructor(self): ident = Affine.identity() assert isinstance(ident, Affine) assert \ tuple(ident) == \ (1, 0, 0, 0, 1, 0, 0, 0, 1) assert ident.is_identity
def test_determinant(self): assert Affine.identity().determinant == 1 assert Affine.scale(2).determinant == 4 assert Affine.scale(0).determinant == 0 assert Affine.scale(5, 1).determinant == 5 assert Affine.scale(-1, 1).determinant == -1 assert Affine.scale(-1, 0).determinant == 0 assert Affine.rotation(77).determinant == pytest.approx(1) assert Affine.translation(32, -47).determinant == pytest.approx(1)
def test_determinant(self): assert_equal(Affine.identity().determinant, 1) assert_equal(Affine.scale(2).determinant, 4) assert_equal(Affine.scale(0).determinant, 0) assert_equal(Affine.scale(5, 1).determinant, 5) assert_equal(Affine.scale(-1, 1).determinant, -1) assert_equal(Affine.scale(-1, 0).determinant, 0) assert_almost_equal(Affine.rotation(77).determinant, 1) assert_almost_equal(Affine.translation(32, -47).determinant, 1)
def test_eccentricity(): assert Affine.identity().eccentricity == 0.0 assert Affine.scale(2).eccentricity == 0.0 #assert_equal(Affine.scale(0).eccentricity, ?) assert Affine.scale(2, 1).eccentricity == pytest.approx(math.sqrt(3) / 2) assert Affine.scale(2, 3).eccentricity == pytest.approx(math.sqrt(5) / 3) assert Affine.scale(1, 0).eccentricity == 1.0 assert Affine.rotation(77).eccentricity == pytest.approx(0.0) assert Affine.translation(32, -47).eccentricity == pytest.approx(0.0) assert Affine.scale(-1, 1).eccentricity == pytest.approx(0.0)
def test_geometry_mask_invalid_shape(basic_geometry): """A width==0 or height==0 should fail with ValueError""" for shape in [(0, 0), (1, 0), (0, 1)]: with pytest.raises(ValueError) as exc_info: geometry_mask([basic_geometry], out_shape=shape, transform=Affine.identity()) assert 'must be > 0' in exc_info.value.args[0]
def test_geometry_mask(basic_geometry, basic_image_2x2): with rasterio.drivers(): assert numpy.array_equal( basic_image_2x2 == 0, geometry_mask( [basic_geometry], out_shape=DEFAULT_SHAPE, transform=Affine.identity() ) )
def test_rotation_constructor_with_pivot(self): assert_equal(tuple(Affine.rotation(60)), tuple(Affine.rotation(60, pivot=(0,0)))) rot = Affine.rotation(27, pivot=(2,-4)) r = math.radians(27) s, c = math.sin(r), math.cos(r) assert_equal(tuple(rot), (c,s,2 - 2*c - 4*s, -s,c,-4 - 2*s + 4*c, 0,0,1)) assert_equal(tuple(Affine.rotation(0, (-3, 2))), tuple(Affine.identity()))
def test_write_plus_mode_requires_width(): """Width is required""" with MemoryFile() as memfile: with pytest.raises(TypeError): memfile.open(driver='GTiff', dtype='uint8', count=3, height=32, crs='epsg:3226', transform=Affine.identity() * Affine.scale(0.5, -0.5))
def warp_affine_rio(src: np.ndarray, dst: np.ndarray, A: Affine, resampling: Resampling, src_nodata: Nodata = None, dst_nodata: Nodata = None, **kwargs) -> np.ndarray: """ Perform Affine warp using rasterio as backend library. :param src: image as ndarray :param dst: image as ndarray :param A: Affine transformm, maps from dst_coords to src_coords :param resampling: str|rasterio.warp.Resampling resampling strategy :param src_nodata: Value representing "no data" in the source image :param dst_nodata: Value to represent "no data" in the destination image **kwargs -- any other args to pass to ``rasterio.warp.reproject`` :returns: dst """ crs = _WRP_CRS src_transform = Affine.identity() dst_transform = A if isinstance(resampling, str): resampling = resampling_s2rio(resampling) dst0 = dst # TODO: GDAL doesn't support signed 8-bit values, so we coerce to uint8, # *BUT* this is only valid for nearest|mode resampling strategies, proper # way is to perform warp in int16 space and then convert back to int8 with # clamping. if dst.dtype.name == 'int8': dst = dst.view('uint8') if dst_nodata is not None: dst_nodata = int(np.uint8(dst_nodata)) if src.dtype.name == 'int8': src = src.view('uint8') if src_nodata is not None: src_nodata = int(np.uint8(src_nodata)) rasterio.warp.reproject(src, dst, src_transform=src_transform, dst_transform=dst_transform, src_crs=crs, dst_crs=crs, resampling=resampling, src_nodata=src_nodata, dst_nodata=dst_nodata, **kwargs) return dst0
def test_is_degenerate(self): assert not Affine.identity().is_degenerate assert not Affine.translation(2, -1).is_degenerate assert not Affine.shear(0, -22.5).is_degenerate assert not Affine.rotation(88.7).is_degenerate assert not Affine.scale(0.5).is_degenerate assert Affine.scale(0).is_degenerate assert Affine.scale(-10, 0).is_degenerate assert Affine.scale(0, 300).is_degenerate assert Affine.scale(0).is_degenerate assert Affine.scale(0).is_degenerate
def test_geometry_mask_invalid_shape(basic_geometry): """A width==0 or height==0 should fail with ValueError""" for shape in [(0, 0), (1, 0), (0, 1)]: with pytest.raises(ValueError) as exc_info: geometry_mask( [basic_geometry], out_shape=shape, transform=Affine.identity()) assert 'must be > 0' in exc_info.value.args[0]
def test_raster_geometrymask(basic_image_2x2, basic_image_file, basic_geometry): """Pixels inside the geometry are False in the mask""" geometries = [basic_geometry] with rasterio.open(basic_image_file) as src: geometrymask, transform, window = raster_geometry_mask(src, geometries) assert np.array_equal(geometrymask, (basic_image_2x2 == 0)) assert transform == Affine.identity() assert window is None
def test_raster_geometrymask_invert(basic_image_2x2, basic_image_file, basic_geometry): """Pixels inside the geometry are True in the mask""" geometries = [basic_geometry] with rasterio.open(basic_image_file) as src: geometrymask, transform, window = raster_geometry_mask(src, geometries, invert=True) assert np.array_equal(geometrymask, basic_image_2x2) assert transform == Affine.identity()
def test_geometry_mask_invert(basic_geometry, basic_image_2x2): with Env(): assert np.array_equal( basic_image_2x2, geometry_mask( [basic_geometry], out_shape=DEFAULT_SHAPE, transform=Affine.identity(), invert=True ) )
def test_rotation_constructor(self): rot = Affine.rotation(60) assert isinstance(rot, Affine) r = math.radians(60) s, c = math.sin(r), math.cos(r) assert_equal(tuple(rot), (c,s,0, -s,c,0, 0,0,1)) rot = Affine.rotation(337) r = math.radians(337) s, c = math.sin(r), math.cos(r) seq_almost_equal(tuple(rot), (c,s,0, -s,c,0, 0,0,1)) assert_equal(tuple(Affine.rotation(0)), tuple(Affine.identity()))
def test_reproject_init_dest_nodata(): """No pixels should transfer over""" crs = CRS.from_epsg(4326) transform = Affine.identity() source = np.zeros((1, 100, 100)) destination = np.ones((1, 100, 100)) reproject( source, destination, src_crs=crs, src_transform=transform, dst_crs=crs, dst_transform=transform, src_nodata=0, init_dest_nodata=False ) assert destination.all()
def test_scale_constructor(self): scale = Affine.scale(5) assert isinstance(scale, Affine) assert \ tuple(scale) == \ (5, 0, 0, 0, 5, 0, 0, 0, 1) scale = Affine.scale(-1, 2) assert \ tuple(scale) == \ (-1, 0, 0, 0, 2, 0, 0, 0, 1) assert tuple(Affine.scale(1)) == tuple(Affine.identity())
def test_geometry_invalid_geom(): """An invalid geometry should fail""" invalid_geoms = [ {'type': 'Invalid'}, # wrong type {'type': 'Point'}, # missing coordinates {'type': 'Point', 'coordinates': []} # empty coordinates ] for geom in invalid_geoms: with pytest.raises(ValueError) as exc_info: geometry_mask( [geom], out_shape=DEFAULT_SHAPE, transform=Affine.identity()) assert 'Invalid geometry' in exc_info.value.args[0]
def test_affine_identity(tmpdir): """ Setting a transform with absolute values equivalent to Affine.identity() should result in a warning (not captured here) and read with affine that matches Affine.identity(). """ output = str(tmpdir.join('test.tif')) out_affine = Affine(1, 0, 0, 0, -1, 0) with rasterio.open( output, 'w', driver='GTiff', count=1, dtype=rasterio.uint8, width=1, height=1, transform=out_affine ) as out: assert out.affine == out_affine with rasterio.open(output) as out: assert out.affine == Affine.identity()
def align_image(affine, infile, outfile=None): """ Create a GDAL VRT referencing the original dataset with an aligned georeference. If no `outfile` argument is specified, the dataset will be created in the same place with `.aligned.vrt` appended as an extension. """ trans = get_transform(infile) px_size = N.array([trans.a,trans.e]) s = Affine.scale(*px_size) px_trans = ~s*affine if outfile is None: outfile = splitext(infile)[0] + ".aligned.vrt" run("gdal_translate", "-of VRT", infile, outfile) if affine != Affine.identity(): outtrans = trans*px_trans*s set_transform(outfile, outtrans) return outfile