def test_calculate_src_window_nonexact(): bounds = BoundingBox(0, 0, 10, 10) transform = Affine(5., 0., 0., 0., -5., 10.) dst_bounds = BoundingBox(-1., 0., 12, 13) ans = geom.calculate_src_window(bounds, transform, dst_bounds) assert ans[0] == Window(0, 0, 2, 2) assert ans[1] == bounds
def get_bounds(ds): """Extract the bounding box in projection coordinates. Parameters ---------- ds : xarray.Dataset The input dataset Returns ------- tuple The bounding box in projection coordinates (left, bottom, right, top). """ trans = get_transform(ds) if trans is not None: if isinstance(ds, xr.Dataset): dims = ds.dims elif isinstance(ds, xr.DataArray): dims = dict(zip(ds.dims, ds.shape)) nrows = dims['y'] ncols = dims['x'] corners = (np.array([0, 0, ncols - 1, ncols - 1]), np.array([0, nrows - 1, 0, nrows - 1])) corner_x, corner_y = trans * corners return BoundingBox(left=corner_x.min(), bottom=corner_y.min(), right=corner_x.max(), top=corner_y.max()) else: return BoundingBox(left=ds['x'].min(), bottom=ds['y'].min(), right=ds['x'].max(), top=ds['y'].max())
def test_mask_image(self): with self.assertRaises(TypeError, msg="bbox must be of type tuple or Shapely Polygon"): self.img.mask([1, 2, 3]) self.img.mask(box(11.9027457562112939, 51.4664152338322580, 11.9477435281016131, 51.5009522690838750,)) self.assertEqual( self.img.dataset.bounds, BoundingBox( left=11.902702941366716, bottom=51.46639813686387, right=11.947798368783504, top=51.50098327545026, ), ) self.img.mask((11.9027457562112939, 51.4664152338322580, 11.9477435281016131, 51.5009522690838750,)) self.assertEqual( self.img.dataset.bounds, BoundingBox( left=11.902702941366716, bottom=51.46639813686387, right=11.947798368783504, top=51.50098327545026, ), ) self.img.mask( box(11.8919236802142620, 51.4664152338322580, 11.9477435281016131, 51.5009522690838750,), fill=True, ) self.assertEqual( self.img.dataset.bounds, BoundingBox( left=11.891923157920472, bottom=51.46639813686387, right=11.947798368783504, top=51.50098327545026 ), )
def test_calculate_dst_window(): src_bounds = BoundingBox(0, 0, 120, 120) dst_transform = Affine(30., 0., 0, 0., -30., 120) ans = geom.calculate_dst_window(src_bounds, dst_transform) assert ans == Window(0, 0, 4, 4) # dst_transform further left & up src_bounds = BoundingBox(0, 0, 65, 95) dst_transform = Affine(30., 0., -35, 0., -30., 155) ans = geom.calculate_dst_window(src_bounds, dst_transform) assert ans == Window(1, 2, 2, 3)
def _inspect_coords(y, x, center=True, assume_unique=True): # returns transform, bounds, shape y_ = np.atleast_1d(y) x_ = np.atleast_1d(x) if not assume_unique: logger.warning('Computing unique values of coordinates...') y_ = np.unique(y_) x_ = np.unique(x_) minmax_y = y_[0], y_[-1] minmax_x = x_[0], x_[-1] if minmax_y[0] > minmax_y[1]: logger.warning('Unreversing y coordinate min/max') minmax_y = (minmax_y[1], minmax_y[0]) # If spacing is not equal we guess from `(max - min) / n` dy = _check_spacing(y_) if dy is False: warnings.warn('"y" coordinate does not have equal spacing') ny = len(y_) dy = (minmax_y[0] - minmax_y[1]) / (ny - 1) else: ny = (minmax_y[0] - minmax_y[1]) / dy # np.unique returns sorted y so dy is negative, but not if unsorted if not assume_unique: dy *= -1 dx = _check_spacing(x_) if dx is False: warnings.warn('"x" coordinate does not have equal spacing') nx = len(x_) dx = (minmax_x[1] - minmax_x[0]) / (nx - 1) else: nx = (minmax_x[1] - minmax_x[0]) / dx transform = Affine(dx, 0.0, minmax_x[0], 0., dy, minmax_y[1]) if center: # affine transform is relative to upper-left, not pixel center transform = transform * Affine.translation(-0.5, -0.5) # create bounds that cover pixel area bounds = BoundingBox(minmax_x[0] - dx / 2, minmax_y[0] + dy / 2, minmax_x[1] + dx / 2, minmax_y[1] - dy / 2) else: # create bounds that cover pixel area bounds = BoundingBox(minmax_x[0], minmax_y[0] + dy, minmax_x[1] + dx, minmax_y[1]) return transform, bounds, (nx, ny)
def test_attribute_compare_bounds(): from rasterio.coords import BoundingBox props = ['bounds'] values = [BoundingBox(0, 0, 1, 1)] src1 = mockobj(props, values) values = [BoundingBox(0, 0, 2, 2)] src2 = mockobj(props, values) compared = raster_tester.compare_properties(src1, src2, props) assert compared == [{ 'bounds': { 'src1': BoundingBox(left=0, bottom=0, right=1, top=1), 'src2': BoundingBox(left=0, bottom=0, right=2, top=2) } }]
def test_4326_not_crossing(): crs = {'init': 'epsg:4326'} boundsArr = densify(make_bounds_array(BoundingBox(-120., 45., -115., 50.))) transformedBounds = transform_bounds(boundsArr, crs) assert not winding_order(transformedBounds)
def get_bounds(datasets, crs): left = min([d.extent.to_crs(crs).boundingbox.left for d in datasets]) right = max([d.extent.to_crs(crs).boundingbox.right for d in datasets]) top = max([d.extent.to_crs(crs).boundingbox.top for d in datasets]) bottom = min([d.extent.to_crs(crs).boundingbox.bottom for d in datasets]) return GeoPolygon.from_boundingbox(BoundingBox(left, bottom, right, top), crs)
def bounds(self): geo_ref_points = self.metadata_doc['grid_spatial']['projection'][ 'geo_ref_points'] return BoundingBox(geo_ref_points['ll']['x'], geo_ref_points['ll']['y'], geo_ref_points['ur']['x'], geo_ref_points['ur']['y'])
def test_sun_elev_calc(sun_elev_test_data): for d in sun_elev_test_data: pred_sun_el = sun_utils.sun_elevation(BoundingBox(*d['bbox']), (10, 10), d['date_acquired'], d['scene_center_time']) assert pred_sun_el.max() > d['mtl_sun_elevation'] assert pred_sun_el.min() < d['mtl_sun_elevation']
def bounds(self): """ Get bounding box. """ return BoundingBox(*(self.transform * (0, self.shape[0])) + (self.transform * (self.shape[1], 0)))
def bounds_intersection(*bounds): """Return the intersection of some BoundingBox(s) Parameters ---------- bounds : BoundingBox Bounding boxes Returns ------- BoundingBox The intersection of all input BoundingBox """ assert len(bounds) > 0 assert all([ isinstance(b, BoundingBox) or (list_like(b) and len(b) == 4) for b in bounds ]) left = max([b[0] for b in bounds]) bottom = max([b[1] for b in bounds]) right = min([b[2] for b in bounds]) top = min([b[3] for b in bounds]) return BoundingBox(left, bottom, right, top)
def bounds_union(*bounds): """Return the union of some BoundingBox(s) Parameters ---------- bounds : BoundingBox Bounding boxes Returns ------- BoundingBox The union of all input BoundingBox """ assert len(bounds) > 0 assert all([ isinstance(b, BoundingBox) or (list_like(b) and len(b) == 4) for b in bounds ]) xs, ys = [], [] for b in bounds: left, bottom, right, top = b xs.extend([left, right]) ys.extend([bottom, top]) return BoundingBox(min(xs), min(ys), max(xs), max(ys))
def test_transform_to_coords_bbox(transform, off_y, off_x): left = transform.c + off_x * transform.a top = transform.f + off_y * transform.e right = left + off_x * transform.a bottom = top + off_y * transform.e bbox = BoundingBox(left, bottom, right, top) y, x = coords.transform_to_coords(transform, bbox=bbox, center=False) # Was the bbox evenly offset? if int(off_y) == off_y: assert y.max() == top assert y.min() + transform.e == bottom assert len(y) == off_y # Or was it not aligned to grid set by transform? else: # Should cover extent and have more area assert y.max() > top assert y.min() + transform.e < bottom assert y.max() - y.min() > top - (bottom - transform.e) if int(off_x) == off_x: assert x.max() + transform.a == right assert x.min() == left assert len(x) == off_x else: # Should cover extent and have more area assert x.max() + transform.a > right assert x.min() < left assert x.max() - x.min() > (right - transform.a) - left
def get_common_bounds(datasets): """Calculate the common bounding box of the input datasets. Parameters ---------- datasets : list of xarray.Dataset The input datasets. Returns ------- tuple The common bounding box (left, bottom, right, top) in projected coordinates. """ bounds = [] common_crs = get_crs(datasets[0]) for ds in datasets: ds_bounds = get_bounds(ds) crs = get_crs(ds) proj_bounds = rasterio.warp.transform_bounds(crs, common_crs, **ds_bounds._asdict()) bounds.append(proj_bounds) # Get largest extent: bounds = np.array(bounds) common_bounds = np.concatenate( (bounds[:, :2].min(axis=0), bounds[:, 2:].max(axis=0))) return BoundingBox(*common_bounds)
def get_tile_bounds(self, grid_id) -> BoundingBox: """BBox for a given tile.""" nb_tiles = int(math.sqrt(self.nb_tiles)) _row, _col = grid_id.split("_") row = int(_row[:-1]) col = int(_col[:-1]) # Top left corner is (0,0) false_easting = self.bounds.left * -1 false_southing = self.bounds.top * -1 grid_height = self.bounds.top + self.bounds.bottom + (2 * false_southing) grid_width = self.bounds.left + self.bounds.right + (2 * false_easting) tile_height = grid_height / nb_tiles tile_width = grid_width / nb_tiles tile_left = col * tile_width - false_easting tile_right = (col + 1) * tile_width - false_easting tile_top = row * tile_height - false_southing tile_bottom = (row + 1) * tile_height - false_southing return BoundingBox( left=tile_left, top=tile_top, right=tile_right, bottom=tile_bottom )
def test_reproject(generator): src_crs = epsg4326 dst_crs = sinusoidal ds = generator(crs=src_crs) src_bounds = get_bounds(ds) dst_bounds_latlon = BoundingBox( left=src_bounds.left - 1, bottom=src_bounds.bottom - 1, right=src_bounds.right + 1, top=src_bounds.top + 1, ) dst_bounds = BoundingBox(*rasterio.warp.transform_bounds( src_crs, dst_crs, **dst_bounds_latlon._asdict())) dst_width, dst_height = 35, 21 resx = (dst_bounds.right - dst_bounds.left) / (dst_width - 1) resy = (dst_bounds.bottom - dst_bounds.top) / (dst_height - 1) res = (abs(resx), abs(resy)) xoff = dst_bounds.left yoff = dst_bounds.top dst_transform = Affine(resx, 0, xoff, 0, resy, yoff) projected = [ _reproject(ds, dst_crs=dst_crs, dst_transform=dst_transform, width=dst_width, height=dst_height), _reproject(ds, dst_crs=dst_crs, dst_transform=dst_transform, extent=dst_bounds), _reproject(ds, dst_crs=dst_crs, extent=dst_bounds, res=res), _reproject(ds, dst_crs=dst_crs, extent=dst_bounds, width=dst_width, height=dst_height) ] for proj in projected[1:]: xr_assert_equal(proj, projected[0]) assert_almost_equal(get_resolution(proj), res) assert_almost_equal(get_bounds(proj), dst_bounds) assert_almost_equal(get_transform(proj), dst_transform) assert_equal_crs(get_crs(proj), dst_crs)
def test_reprojection_with_target(generator): src_crs = epsg4326 dst_crs = sinusoidal ds = generator(crs=src_crs) src_bounds = warp.get_bounds(ds) dst_bounds_latlon = BoundingBox( left=src_bounds.left - 1, bottom=src_bounds.bottom - 1, right=src_bounds.right + 1, top=src_bounds.top + 1, ) dst_bounds = BoundingBox(*rasterio.warp.transform_bounds( src_crs, dst_crs, **dst_bounds_latlon._asdict() )) dst_width, dst_height = 35, 21 resx = (dst_bounds.right - dst_bounds.left) / (dst_width - 1) resy = (dst_bounds.bottom - dst_bounds.top) / (dst_height - 1) res = (abs(resx), abs(resy)) xoff = dst_bounds.left yoff = dst_bounds.top dst_transform = Affine(resx, 0, xoff, 0, resy, yoff) target = generator( dims={'x': dst_width, 'y': dst_height, 'time': 1}, extent=dst_bounds, crs=dst_crs ) projected = [ warp.Reprojection(crs=dst_crs, transform=dst_transform, width=dst_width, height=dst_height).apply(ds), warp.Reprojection(crs=dst_crs, extent=dst_bounds, res=res).apply(ds), warp.Reprojection(crs=dst_crs, extent=dst_bounds, width=dst_width, height=dst_height).apply(ds), warp.Reprojection(target=target).apply(ds), ] for i, proj in enumerate(projected[1:]): print(i) xr_assert_equal(proj, projected[0]) assert_almost_equal(warp.get_resolution(proj), res) assert_almost_equal(warp.get_bounds(proj), dst_bounds) assert_almost_equal(warp.get_transform(proj), dst_transform) assert_equal_crs(warp.get_crs(proj), dst_crs)
def global_reader_invalid_bounds(path=''): reader = Mock(spec=RasterReader) reader.shape = (360, 720) reader.affine = Affine(-180., 0.5, 0.0, 90., 0.0, -0.5) reader.bounds = BoundingBox(-180., 90., 0.5, 0.) context = Mock() context.__enter__ = Mock(return_value=reader) context.__exit__ = Mock(return_value=False) return context
def round_bounds(bounds): # TODO thesis, round method ceil, floor attrs = ('left', 'bottom', 'right', 'top') coords = [] for attr in attrs: coord = bounds.__getattribute__(attr) coords.append(round(coord)) return BoundingBox(*coords)
def test_bounds_tranform_union_1(): # Should all be the same n = 3 bounds = BoundingBox(365385.0, 2901915.0, 380385.0, 2916915.0) transform = Affine(30.0, 0.0, 365385.0, 0.0, -30.0, 2916915.0) test = geom.bounds_transform_union((bounds, ) * n, transform) assert test[0] == bounds assert test[1] == transform assert test[2][0] == int((bounds.top - bounds.bottom) / 30) assert test[2][1] == int((bounds.right - bounds.left) / 30)
def get_image_bound_box(file_path, buffer=None): # get the bounding box: (left, bottom, right, top) with rasterio.open(file_path) as src: # the extent of the raster raster_bounds = src.bounds if buffer is not None: # Create new instance of BoundingBox(left, bottom, right, top) new_box_obj = BoundingBox(raster_bounds.left-buffer, raster_bounds.bottom-buffer, raster_bounds.right+buffer, raster_bounds.top+ buffer) # print(raster_bounds, new_box_obj) return new_box_obj return raster_bounds
def roi_to_tiles(self, roi): """ Yield tiles overlapping a Region of Interest `shapely` geometry Args: roi (shapely.geometry.Polygon): A geometry in the tile specifications' crs Yields: Tile: A :class`Tile` that intersects the ROI """ bounds = BoundingBox(roi.bounds) grid_ys, grid_xs = self._frame_bounds(bounds) return self._yield_tiles(grid_ys, grid_xs, bounds)
def bbox_intersection(bounds1, bounds2): if disjoint_bounds(bounds1, bounds2): raise Exception("Bounds are disjoint, no interseciton exists") bbox = BoundingBox( left=max(bounds1.left, bounds2.left), right=min(bounds1.right, bounds2.right), top=min(bounds1.top, bounds2.top), bottom=max(bounds1.bottom, bounds2.bottom) ) return bbox
def _reflectance_worker(open_files, window, ij, g_args): """rio mucho worker for reflectance. It reads input files and perform reflectance calculations on each window. Parameters ------------ open_files: list of rasterio open files window: tuples g_args: dictionary Returns --------- out: None Output is written to dst_path """ data = riomucho.utils.array_stack([ src.read(window=window).astype(np.float32) for src in open_files ]) depth, rows, cols = data.shape if g_args['pixel_sunangle']: bbox = BoundingBox( *warp.transform_bounds( g_args['src_crs'], {'init': u'epsg:4326'}, *open_files[0].window_bounds(window))) E = sun_utils.sun_elevation( bbox, (rows, cols), g_args['date_collected'], g_args['time_collected_utc']).reshape(rows, cols, 1) else: # We're doing whole-scene (instead of per-pixel) sunangle: E = np.array([g_args['E'] for i in range(depth)]) output = toa_utils.rescale( reflectance( data, g_args['M'], g_args['A'], E, g_args['src_nodata']), g_args['rescale_factor'], g_args['dst_dtype'], clip=g_args['clip']) return output
def ingest_cmd(index, config, dry_run, executor): _, config = next(read_documents(Path(config))) source_type = index.datasets.types.get_by_name(config['source_type']) if not source_type: _LOG.error("Source DatasetType %s does not exist", config['source_type']) # print (source_type) # print ("abcdefghijklmnopqrstuvwxyz") output_type = morph_dataset_type(source_type, config) # print (output_type) _LOG.info('Created DatasetType %s', output_type.name) output_type = index.datasets.types.add(output_type) datacube = Datacube(index=index) grid_spec = output_type.grid_spec namemap = get_namemap(config) measurements = get_measurements(source_type, config) variable_params = get_variable_params(config) file_path_template = str( Path(config['location'], config['file_path_template'])) bbox = BoundingBox(**config['ingestion_bounds']) tasks = find_diff(source_type, output_type, bbox, datacube) def ingest_work(tile_index, sources): geobox = GeoBox.from_grid_spec(grid_spec, tile_index) # print ("in ingest.py in ingest_word") data = Datacube.product_data(sources, geobox, measurements) nudata = data.rename(namemap) file_path = file_path_template.format( tile_index=tile_index, start_time=to_datetime( sources.time.values[0]).strftime('%Y%m%d%H%M%S%f'), end_time=to_datetime( sources.time.values[-1]).strftime('%Y%m%d%H%M%S%f')) # TODO: algorithm params print("Writing product") nudatasets = write_product(nudata, sources, output_type, config['global_attributes'], variable_params, Path(file_path)) return nudatasets do_work(tasks, ingest_work, index, executor) temp = str(Path(config['location'])) files_path = temp + "/cache" if not os.path.isfile(temp + "/archive"): os.system("mkdir " + temp + "/archive") print("Compressing files") compress(files_path)
def test_sun_angle3(test_data): # South, Winter mtl = test_data[2] mtl_sun = mtl['L1_METADATA_FILE']['IMAGE_ATTRIBUTES']['SUN_ELEVATION'] bbox = BoundingBox(*toa_utils._get_bounds_from_metadata( mtl['L1_METADATA_FILE']['PRODUCT_METADATA'])) sunangles = sun_utils.sun_elevation( bbox, (100, 100), mtl['L1_METADATA_FILE']['PRODUCT_METADATA']['DATE_ACQUIRED'], mtl['L1_METADATA_FILE']['PRODUCT_METADATA']['SCENE_CENTER_TIME']) assert sunangles[49][49] - mtl_sun < 5
def reader_context(**attrs): reader = Mock( spec=DatasetReader, shape=(360, 720), transform=Affine(-180., 0.5, 0.0, -90., 0.0, 0.5), bounds=BoundingBox(-180., -90., 0., 0.), crs={"init": "epsg:4326"}, ) reader.configure_mock(**attrs) context = Mock() context.__enter__ = Mock(return_value=reader) context.__exit__ = Mock(return_value=False) return context
def get_extent(ds): """Extract the extent (bounding box) from the dataset. Parameters ---------- ds : xarray.Dataset The input dataset Returns ------- tuple The extent (left, bottom, right, top) in latitude and longitude coordinates. """ # # Check if latitude and longitude are stored as coordinates. # if 'lon' in ds.coords and 'lat' in ds.coords: return BoundingBox(left=ds.lon.values.min(), bottom=ds.lat.values.min(), right=ds.lon.values.max(), top=ds.lat.values.max()) # # Otherwise, get extent from projection information # by projecting the corner coordinates onto EPSG:4326 # to obtain the latitude and longitude at the four corners. # src_crs = get_crs(ds) if src_crs is None: raise CRSError('Could not determine the CRS.') dst_crs = CRS(init='epsg:4326') proj_bounds = get_bounds(ds) bounds = rasterio.warp.transform_bounds(src_crs, dst_crs, **proj_bounds._asdict()) return BoundingBox(*bounds)
def _grid_datasets(datasets, bounds_override, grid_proj, grid_size): tiles = defaultdict(list) for dataset in datasets: dataset_proj = dataset.crs dataset_bounds = dataset.bounds bounds = bounds_override or BoundingBox(*transform_bounds(dataset_proj, grid_proj, *dataset_bounds)) for y in range(int(bounds.bottom // grid_size[1]), int(bounds.top // grid_size[1]) + 1): for x in range(int(bounds.left // grid_size[0]), int(bounds.right // grid_size[0]) + 1): tile_index = (x, y) if _check_intersect(tile_index, grid_size, grid_proj, dataset_bounds, dataset_proj): tiles[tile_index].append(dataset) return tiles