def test_wgs84_invariance(self): lats = [-10, 0, 10] lons = [-170, 0, 100] wgs84_epsg = WGS84_LATLON_EPSG xs, ys = utils.reproject_latlons(lats, lons, epsg=wgs84_epsg) assert lats == ys assert lons == xs
def test_only_one_projection_format_can_be_provided(self): with pytest.raises(ValueError): lats = [-10, 0, 10] lons = [-170, 0, 100] xs, ys = utils.reproject_latlons( lats, lons, epsg=WGS84_LATLON_EPSG, wkt=WGS84_LATLON_WKT )
def test_utm_conversion(self): lats = [10.5] lons = [120.8] epsg = 32651 xs, ys = utils.reproject_latlons(lats, lons, epsg=epsg) x = 259212 y = 1161538 assert np.allclose(x, xs) assert np.allclose(y, ys)
def location_paths(self, lats, lons): """File corresponding to each location. Args: lats, lons: Lists of locations. Returns: List of filenames, same length as locations. """ lats = np.asarray(lats) lons = np.asarray(lons) # Convert to filename projection. xs, ys = utils.reproject_latlons(lats, lons, epsg=self.filename_epsg) # Find corresponding tile. filenames = self._location_to_tile_corner(xs, ys, self.filename_tile_size) paths = [self._tile_lookup.get(f) for f in filenames] return paths
def location_paths(self, lats, lons): """File corresponding to each location. Args: lats, lons: Lists of locations. Returns: List of filenames, same length as locations. """ lats = np.asarray(lats) lons = np.asarray(lons) # Convert to filename projection. xs, ys, = utils.reproject_latlons(lats, lons, epsg=self.filename_epsg) # Use to look up. filenames = self.__class__._location_to_tile_name( xs, ys, self.filename_tile_size, self.ns_fixed_width, self.ew_fixed_width) paths = [self._tile_lookup.get(f) for f in filenames] return paths
def _get_elevation_from_path(lats, lons, path, interpolation): """Read values at locations in a raster. Args: lats, lons: Arrays of latitudes/longitudes. path: GDAL supported raster location. interpolation: method name string. Returns: z_all: List of elevations, same length as lats/lons. """ z_all = [] interpolation = INTERPOLATION_METHODS.get(interpolation) lons = np.asarray(lons) lats = np.asarray(lats) try: with rasterio.open(path) as f: if f.crs is None: msg = "Dataset has no coordinate reference system." msg += f" Check the file '{path}' is a geo raster." msg += " Otherwise you'll have to add the crs manually with a tool like gdaltranslate." raise InputError(msg) try: if f.crs.is_epsg_code: xs, ys = utils.reproject_latlons(lats, lons, epsg=f.crs.to_epsg()) else: xs, ys = utils.reproject_latlons(lats, lons, wkt=f.crs.to_wkt()) except ValueError: raise InputError( "Unable to transform latlons to dataset projection.") # Check bounds. oob_indices = _validate_points_lie_within_raster( xs, ys, lats, lons, f.bounds, f.res) rows, cols = tuple(f.index(xs, ys, op=_noop)) # Offset by 0.5 to convert from center coords (provided by # f.index) to ul coords (expected by f.read). rows = np.array(rows) - 0.5 cols = np.array(cols) - 0.5 # Because of floating point precision, indices may slightly exceed # array bounds. Because we've checked the locations are within the # file bounds, it's safe to clip to the array shape. rows = rows.clip(0, f.height - 1) cols = cols.clip(0, f.width - 1) # Read the locations, using a 1x1 window. The `masked` kwarg makes # rasterio replace NODATA values with np.nan. The `boundless` kwarg # forces the windowed elevation to be a 1x1 array, even when it all # values are NODATA. for i, (row, col) in enumerate(zip(rows, cols)): if i in oob_indices: z_all.append(None) continue window = rasterio.windows.Window(col, row, 1, 1) z_array = f.read( indexes=1, window=window, resampling=interpolation, out_dtype=float, boundless=True, masked=True, ) z = np.ma.filled(z_array, np.nan)[0][0] z_all.append(z) # Depending on the file format, when rasterio finds an invalid projection # of file, it might load it with a None crs, or it might throw an error. except rasterio.RasterioIOError as e: if "not recognized as a supported file format" in str(e): msg = f"Dataset file '{path}' not recognised as a geo raster." msg += " Check that the file has projection information with gdalsrsinfo," msg += " and that the file is not corrupt." raise InputError(msg) raise e return z_all
def test_no_projection_provided(self): with pytest.raises(ValueError): lats = [10.5] lons = [120.8] xs, ys = utils.reproject_latlons(lats, lons)
def test_bad_epsg(self): with pytest.raises(ValueError): lats = [10.5] lons = [120.8] epsg = 0 xs, ys = utils.reproject_latlons(lats, lons, epsg=epsg)
def test_cache_gets_populated(self): lats = [10.5] lons = [120.8] assert NAD83_WKT not in utils._TRANSFORMER_CACHE utils.reproject_latlons(lats, lons, wkt=NAD83_WKT) assert NAD83_WKT in utils._TRANSFORMER_CACHE