def test_transform(): pj_utm = osr_util.get_srs(32636) utm_x = [690950.4640, 688927.6381] utm_y = [3431318.8435, 3542183.4911] for gis_order in (False, True): axis_order = osr_util.get_axis_order_from_gis_order(gis_order) pj4326 = osr_util.get_srs(4326, axis_order=axis_order) ct = osr_util.get_transform(pj4326, pj_utm) lon = [35, 35] lat = [31, 32] x, y = (lon, lat) if gis_order else (lat, lon) osr_util.transform_points(ct, x, y) d = array_util.array_dist(x, utm_x), array_util.array_dist(y, utm_y) assert max(d) < 0.01
def gdallocationinfo( filename_or_ds: PathOrDS, x: ArrayOrScalarLike, y: ArrayOrScalarLike, srs: CoordinateTransformationOrSRS = None, axis_order: Optional[OAMS_AXIS_ORDER] = None, open_options: Optional[dict] = None, ovr_idx: Optional[int] = None, band_nums: Optional[Sequence[int]] = None, inline_xy_replacement: bool = False, return_ovr_pixel_line: bool = False, transform_round_digits: Optional[float] = None, allow_xy_outside_extent: bool = True, pixel_offset: Real = -0.5, line_offset: Real = -0.5, resample_alg=gdalconst.GRIORA_NearestNeighbour, quiet_mode: bool = True, ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ds = open_ds(filename_or_ds, open_options=open_options) filename = filename_or_ds if is_path_like(filename_or_ds) else '' if ds is None: raise Exception(f'Could not open {filename}.') if not isinstance(x, ArrayLike.__args__): x = [x] if not isinstance(y, ArrayLike.__args__): y = [y] if len(x) != len(y): raise Exception( f'len(x)={len(x)} should be the same as len(y)={len(y)}') point_count = len(x) dtype = np.float64 if not isinstance(x, np.ndarray) or not isinstance(y, np.ndarray): x = np.array(x, dtype=dtype) y = np.array(y, dtype=dtype) inline_xy_replacement = True if srs is None: srs = LocationInfoSRS.PixelLine # Build Spatial Reference object based on coordinate system, fetched from the opened dataset if srs != LocationInfoSRS.PixelLine: if srs != LocationInfoSRS.SameAsDS_SRS: ds_srs = ds.GetSpatialRef() ct = None if isinstance(srs, osr.CoordinateTransformation): ct = srs else: if srs == LocationInfoSRS.SameAsDS_SRS_GeogCS: points_srs = ds_srs.CloneGeogCS() else: points_srs = get_srs(srs, axis_order=axis_order) ct = get_transform(points_srs, ds_srs) if ct is not None: if not inline_xy_replacement: x = x.copy() y = y.copy() inline_xy_replacement = True transform_points(ct, x, y) if transform_round_digits is not None: x.round(transform_round_digits, out=x) y.round(transform_round_digits, out=y) # Read geotransform matrix and calculate corresponding pixel coordinates geotransform = ds.GetGeoTransform() inv_geotransform = gdal.InvGeoTransform(geotransform) if inv_geotransform is None: raise Exception("Failed InvGeoTransform()") # can we inline this transformation ? x, y = \ (inv_geotransform[0] + inv_geotransform[1] * x + inv_geotransform[2] * y), \ (inv_geotransform[3] + inv_geotransform[4] * x + inv_geotransform[5] * y) inline_xy_replacement = True xsize, ysize = ds.RasterXSize, ds.RasterYSize bands = get_bands(ds, band_nums, ovr_idx=ovr_idx) ovr_xsize, ovr_ysize = bands[0].XSize, bands[0].YSize pixel_fact, line_fact = (ovr_xsize / xsize, ovr_ysize / ysize) if ovr_idx else (1, 1) bnd_count = len(bands) shape = (bnd_count, point_count) np_dtype, np_dtype = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds) results = np.empty(shape=shape, dtype=np_dtype) check_outside = not quiet_mode or not allow_xy_outside_extent if check_outside and (np.any(x < 0) or np.any(x >= xsize) or np.any(y < 0) or np.any(y >= ysize)): msg = 'Passed coordinates are not in dataset extent!' if not allow_xy_outside_extent: raise Exception(msg) elif not quiet_mode: print(msg) if pixel_fact == 1: pixels_q = x elif return_ovr_pixel_line: x *= pixel_fact pixels_q = x else: pixels_q = x * pixel_fact if line_fact == 1: lines_q = y elif return_ovr_pixel_line: y *= line_fact lines_q = y else: lines_q = y * line_fact buf_xsize = buf_ysize = 1 buf_type, typecode = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds) buf_obj = np.empty([buf_ysize, buf_xsize], dtype=typecode) for idx, (pixel, line) in enumerate(zip(pixels_q, lines_q)): for bnd_idx, band in enumerate(bands): if BandRasterIONumPy(band, 0, pixel - 0.5, line - 0.5, 1, 1, buf_obj, buf_type, resample_alg, None, None) == 0: results[bnd_idx][idx] = buf_obj[0][0] is_scaled, scales, offsets = get_scales_and_offsets(bands) if is_scaled: for bnd_idx, (scale, offset) in enumerate(zip(scales, offsets)): results[bnd_idx] = results[bnd_idx] * scale + offset return x, y, results
def test_gdallocationinfo_py_7(): filename_template = 'tmp/byte{}.tif' overview_list = [2] overview_list, file_list = copy_raster_and_add_overviews( filename_src='../gcore/data/byte.tif', output_filename_template=filename_template, overview_list=overview_list) temp_files.extend(file_list) ds = open_ds(filename_template.format('')) ds_srs = ds.GetSpatialRef() gt = ds.GetGeoTransform() ovr_fact = 1 pix_offset = 0 p0 = list(i * ovr_fact + pix_offset for i in range(0, 3)) l0 = list(i * ovr_fact + pix_offset for i in range(0, 3)) p0, l0 = zip(*product(p0, l0)) x0 = list(gt[0] + pixel * gt[1] for pixel in p0) y0 = list(gt[3] + line * gt[5] for line in l0) dtype = np.float64 p0 = np.array(p0, dtype=dtype) l0 = np.array(l0, dtype=dtype) x0 = np.array(x0, dtype=dtype) y0 = np.array(y0, dtype=dtype) expected_results = [[(0.0, 0.0, 107), (0.0, 1.0, 115), (0.0, 2.0, 115), (1.0, 0.0, 123), (1.0, 1.0, 132), (1.0, 2.0, 132), (2.0, 0.0, 132), (2.0, 1.0, 107), (2.0, 2.0, 140)], [(0.0, 0.0, 120), (0.0, 0.5, 120), (0.0, 1.0, 132), (0.5, 0.0, 120), (0.5, 0.5, 120), (0.5, 1.0, 132), (1.0, 0.0, 124), (1.0, 0.5, 124), (1.0, 1.0, 129)]] expected_results = np.array(expected_results, dtype=dtype) do_print = False for ovr_idx, f in enumerate(overview_list): for srs in [ LocationInfoSRS.PixelLine, LocationInfoSRS.SameAsDS_SRS, 4326 ]: if srs == LocationInfoSRS.PixelLine: x = p0 y = l0 elif srs == LocationInfoSRS.SameAsDS_SRS: x = x0 y = y0 else: points_srs = get_srs(srs, axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER) ct = get_transform(ds_srs, points_srs) x = x0.copy() y = y0.copy() transform_points(ct, x, y) pixels, lines, results = gdallocationinfo.gdallocationinfo( filename_or_ds=ds, ovr_idx=ovr_idx, x=x, y=y, transform_round_digits=2, return_ovr_pixel_line=True, srs=srs, axis_order=osr.OAMS_TRADITIONAL_GIS_ORDER) actual = list(zip(pixels, lines, *results)) actual = np.array(actual, dtype=dtype) expected = expected_results[ovr_idx] if do_print: print(actual) print(expected) outputs = list(zip(x, y, pixels, lines, *results)) print( f'ovr: {ovr_idx}, srs: {srs}, x/y/pixel/line/result: {outputs}' ) assert_allclose(expected, actual, rtol=1e-4, atol=1e-3)
def gdallocationinfo( filename_or_ds: PathOrDS, x: NumpyCompatibleArrayOrReal, y: NumpyCompatibleArrayOrReal, gis_order: bool = False, open_options: Optional[dict] = None, ovr_idx: Optional[int] = None, band_nums: Optional[Sequence[int]] = None, srs: CoordinateTransformationOrSRS = None, inline_xy_replacement: bool = True, quiet_mode: bool = True, allow_xy_outside_extent: bool = True, pixel_offset: Real = -0.5, line_offset: Real = -0.5, resample_alg=gdalconst.GRIORA_NearestNeighbour ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ds = open_ds(filename_or_ds, open_options=open_options) filename = filename_or_ds if is_path_like(filename_or_ds) else '' if ds is None: raise Exception(f'Could not open {filename}.') if not isinstance(x, NumpyCompatibleArray.__args__): x = [x] if not isinstance(y, NumpyCompatibleArray.__args__): y = [y] if len(x) != len(y): raise Exception( f'len(x)={len(x)} should be the same as len(y)={len(y)}') point_count = len(x) if not isinstance(x, np.ndarray): x = np.ndarray(x) if not isinstance(y, np.ndarray): y = np.ndarray(y) if srs is None: srs = LocationInfoSRS.PixelLine # Build Spatial Reference object based on coordinate system, fetched from the opened dataset if srs != LocationInfoSRS.PixelLine: if srs != LocationInfoSRS.SameAsDS_SRS: ds_srs = ds.GetSpatialRef() ct = None if isinstance(srs, osr.CoordinateTransformation): ct = srs else: if srs == LocationInfoSRS.SameAsDS_SRS_GeogCS: points_srs = ds_srs.CloneGeogCS() else: points_srs = get_srs(srs, gis_order=gis_order) ct = get_transform(points_srs, ds_srs) x, y, _z = transform_points(ct, x, y) # Read geotransform matrix and calculate corresponding pixel coordinates geomatrix = ds.GetGeoTransform() inv_geometrix = gdal.InvGeoTransform(geomatrix) if inv_geometrix is None: raise Exception("Failed InvGeoTransform()") x, y = \ (inv_geometrix[0] + inv_geometrix[1] * x + inv_geometrix[2] * y), \ (inv_geometrix[3] + inv_geometrix[4] * x + inv_geometrix[5] * y) xsize, ysize = ds.RasterXSize, ds.RasterYSize bands = get_bands(ds, band_nums, ovr_idx=ovr_idx) ovr_xsize, ovr_ysize = bands[0].XSize, bands[0].YSize pixel_fact, line_fact = (ovr_xsize / xsize, ovr_ysize / ysize) if ovr_idx else (1, 1) bnd_count = len(bands) shape = (bnd_count, point_count) np_dtype, np_dtype = GDALTypeCodeAndNumericTypeCodeFromDataSet(ds) results = np.empty(shape=shape, dtype=np_dtype) check_outside = not quiet_mode or not allow_xy_outside_extent if check_outside and (np.any(x < 0) or np.any(x >= xsize) or np.any(y < 0) or np.any(y >= ysize)): msg = 'Passed coordinates are not in dataset extent!' if not allow_xy_outside_extent: raise Exception(msg) elif not quiet_mode: print(msg) pixels = np.clip(x * pixel_fact + pixel_offset, 0, ovr_xsize - 1, out=x if inline_xy_replacement else None) lines = np.clip(y * line_fact + line_offset, 0, ovr_ysize - 1, out=y if inline_xy_replacement else None) for idx, (pixel, line) in enumerate(zip(pixels, lines)): for bnd_idx, band in enumerate(bands): val = band.ReadAsArray(pixel, line, 1, 1, resample_alg=resample_alg) val = val[0][0] results[bnd_idx][idx] = val is_scaled, scales, offsets = get_scales_and_offsets(bands) if is_scaled: for bnd_idx, scale, offset in enumerate(zip(scales, offsets)): results[bnd_idx] = results[bnd_idx] * scale + offset return pixels, lines, results