def test_vector_feature_types(self): eop = EOPatch() invalid_entries = [{}, [], 0, None] for feature_type in FeatureTypeSet.VECTOR_TYPES: for entry in invalid_entries: with self.assertRaises( ValueError, msg='Invalid entry {} for {} should raise an error'. format(entry, feature_type)): eop[feature_type]['TEST'] = entry crs_test = CRS.WGS84.pyproj_crs() geo_test = GeoSeries([BBox((1, 2, 3, 4), crs=CRS.WGS84).geometry], crs=crs_test) eop.vector_timeless['TEST'] = geo_test self.assertTrue(isinstance(eop.vector_timeless['TEST'], GeoDataFrame), 'GeoSeries should be parsed into GeoDataFrame') self.assertTrue(hasattr(eop.vector_timeless['TEST'], 'geometry'), 'Feature should have geometry attribute') self.assertEqual(eop.vector_timeless['TEST'].crs, crs_test, 'GeoDataFrame should still contain the crs') with self.assertRaises( ValueError, msg='Should fail because there is no TIMESTAMP column'): eop.vector['TEST'] = geo_test
def process(self, arguments): data_as_list = self.validate_parameter(arguments, "data", required=True, allowed_types=[list]) dims = self.validate_parameter(arguments, "dims", required=True, allowed_types=[list]) coords = self.validate_parameter(arguments, "coords", allowed_types=[dict], default={}) if "t" in coords: coords["t"] = [ datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in coords["t"] ] data = xr.DataArray( np.array(data_as_list, dtype=np.float), coords=coords, dims=dims, attrs={ "band_aliases": {}, "bbox": BBox(( 12.0, 45.0, 13.0, 46.0, ), CRS(4326)), }, ) self.logger.info(data) return data
def test_bbox_transform(self): bbox = BBox(((111.644, 8.655), (111.7, 8.688)), CRS.WGS84) new_bbox = geo_utils.transform_bbox(bbox, CRS.POP_WEB) expected_bbox = BBox((12428153.23, 967155.41, 12434387.12, 970871.43), CRS.POP_WEB) for coord, expected_coord in zip(new_bbox, expected_bbox): self.assertAlmostEqual(coord, expected_coord, delta=1E-2, msg='Expected coord {}, got {}'.format( expected_coord, coord)) self.assertEqual( new_bbox.get_crs(), expected_bbox.get_crs(), 'Expected CRS {}, got {}'.format(expected_bbox.get_crs(), new_bbox.get_crs()))
def test_bbox_iter(self): bbox_lst = [46.07, 13.23, 46.24, 13.57] bbox = BBox(bbox_lst, CRS.WGS84) bbox_iter = [coord for coord in bbox] self.assertEqual(bbox_iter, bbox_lst, msg="Expected {}, got {}".format(bbox_lst, bbox_iter))
def test_bbox_eq(self): bbox1 = BBox([46.07, 13.23, 46.24, 13.57], CRS.WGS84) bbox2 = BBox(((46.24, 13.57), (46.07, 13.23)), 4326) bbox3 = BBox([46.07, 13.23, 46.24, 13.57], CRS.POP_WEB) bbox4 = BBox([46.07, 13.23, 46.24, 13.58], CRS.WGS84) self.assertEqual( bbox1, bbox2, "Bounding boxes {} and {} should be the same".format( repr(bbox1), repr(bbox2))) self.assertNotEqual( bbox1, bbox3, "Bounding boxes {} and {} should not be the same".format( repr(bbox1), repr(bbox3))) self.assertNotEqual( bbox1, bbox4, "Bounding boxes {} and {} should not be the same".format( repr(bbox1), repr(bbox4)))
def bbox_coord_SENTINEL(lat, long, ang_width): # Define a Bounding Box for sentinel hub coords_wgs84 = [ long - ang_width, lat - ang_width, long + ang_width, lat + ang_width ] bound_box = BBox(bbox=coords_wgs84, crs=CRS.WGS84) return bound_box
def __attrs_post_init__(self): if self.description is None: self.description = '' if self.sampling is None: # TODO: fixme return # TODO: accept non-default geometry max_coord = 2 * 10 ** 7 self.geometry = BBox((-max_coord, -max_coord, max_coord, max_coord), CRS.POP_WEB) if self.input_source.source_type is SourceType.S2_L1C_ARCHIVE: window_shape = self.sampling['window_width'], self.sampling['window_height'] # TODO: replace ShIndexSampling with ShOgcIndexSampling self.sampling_method = ShIndexSampling(window_shape, self.sampling['resolution'], self.sampling['buffer']) elif self.input_source.source_type.is_geopedia_source(): if self.input_source.geopedia_layer == 1749: self.sampling_method = GeopediaOldAppResults(self.input_source) elif self.input_source.geopedia_layer == 2048: window_shape = self.sampling['window_width'], self.sampling['window_height'] self.sampling_method = GeopediaWaterBodySampling(self.input_source, window_shape, self.sampling['resolution']) else: raise NotImplementedError else: raise NotImplementedError
def get_cloud(lefttoplon, lefttoplat, rightbtmlon, rightbtmlat, time): """ Return cloud masks given a bounding box and time """ if abs(lefttoplon) > 180 or abs(rightbtmlon) > 180: print("wrong longitude") return None if abs(lefttoplat) > 90 or abs(rightbtmlat) > 90: print("wrong latitude") return None bands_script = 'return [B01,B02,B04,B05,B08,B8A,B09,B10,B11,B12]' desired_coords_wgs84 = [lefttoplon, lefttoplat, rightbtmlon, rightbtmlat] desired_bbox = BBox(bbox=desired_coords_wgs84, crs=CRS.WGS84) wms_bands_request = WmsRequest( layer='TRUE_COLOR', custom_url_params={CustomUrlParam.EVALSCRIPT: bands_script}, bbox=desired_bbox, time=time, width=100, height=100, image_format=MimeType.TIFF_d32f, instance_id=INSTANCE_ID) all_cloud_masks = CloudMaskRequest(ogc_request=wms_bands_request, threshold=0.4) cloud_dates = all_cloud_masks.get_dates() cloud_masks = all_cloud_masks.get_cloud_masks(threshold=0.4) return cloud_masks, cloud_dates
def get_data(lefttoplon, lefttoplat, rightbtmlon, rightbtmlat, time, maxcc=1, NDWI=True): """ Return the NDWI imageries given a bounding box and time """ if abs(lefttoplon) > 180 or abs(rightbtmlon) > 180: print("wrong longitude") return None if abs(lefttoplat) > 90 or abs(rightbtmlat) > 90: print("wrong latitude") return None if NDWI: layer = 'NDWI' else: layer = 'TRUE_COLOR' desired_coords_wgs84 = [lefttoplon, lefttoplat, rightbtmlon, rightbtmlat] desired_bbox = BBox(bbox=desired_coords_wgs84, crs=CRS.WGS84) wms_request = WmsRequest(layer=layer, bbox=desired_bbox, time=time, maxcc=maxcc, width=100, height=100, instance_id=INSTANCE_ID) wms_img = wms_request.get_data() return wms_img, wms_request.get_dates()
def get_bounding_box(latitude, longtitude, radius=1): dLat = radius / 111.1 dLon = dLat / cos(radians(latitude)) bounding_box_coord = [ longtitude - dLon, latitude - dLat, longtitude + dLon, latitude + dLat ] # print(bounding_box_coord) return BBox(bbox=bounding_box_coord, crs=CRS.WGS84)
def setUp(cls): super().setUpClass() bbox = BBox((111.7, 8.655, 111.6, 8.688), crs=CRS.WGS84) cls.request = WcsRequest(data_folder=cls.OUTPUT_FOLDER, bbox=bbox, data_collection=DataCollection.SENTINEL2_L1C, layer='TRUE-COLOR-S2-L1C')
def test_get_image_dimensions(self): bbox = BBox(((111.644, 8.655), (111.7, 8.688)), CRS.WGS84) width = geo_utils.get_image_dimension(bbox, height=715) height = geo_utils.get_image_dimension(bbox, width=1202) expected_width = 1203 expected_height = 715 self.assertEqual(width, expected_width, msg='Expected width {}, got {}'.format(expected_width, width)) self.assertEqual(height, expected_height, msg='Expected height {}, got {}'.format(expected_height, height))
def setUpClass(cls): bbox = BBox(bbox=[(524358.0140363087, 6964349.630376049), (534141.9536568124, 6974133.5699965535)], crs=CRS.POP_WEB) gpd_request = GeopediaWmsRequest(layer='ttl1917', theme='ml_aws', bbox=bbox, width=50, height=50, image_format=MimeType.PNG) cls.data = gpd_request.get_data()
def test_bbox_from_flat_list(self): for bbox_lst in [[46.07, 13.23, 46.24, 13.57], [46.24, 13.23, 46.07, 13.57], [46.07, 13.57, 46.24, 13.23], [46.24, 13.57, 46.07, 13.23]]: with self.subTest(msg="bbox={}".format(bbox_lst)): bbox = BBox(bbox_lst, CRS.WGS84) self.assertEqual(bbox.lower_left, (46.07, 13.23)) self.assertEqual(bbox.upper_right, (46.24, 13.57)) self.assertEqual(bbox.crs, CRS.WGS84)
def _get_small_bbox(self, point): """ Create a small random bbox from a point for WFS search TODO: sentinelhub-py should support WFS searches with a point object """ x, y = point eps = 0.0001 if self.area_of_interest.crs is CRS.WGS84 else 0.01 return BBox([x - eps, y - eps, x + eps, y + eps], crs=self.area_of_interest.crs)
def setUpClass(cls): super().setUpClass() with open(os.path.join(cls.INPUT_FOLDER, "test_fis_results.txt"), 'r') as file: results = [ast.literal_eval(line.strip()) for line in file] bbox = BBox([14.00, 45.00, 14.03, 45.03], crs=CRS.WGS84) geometry1 = Geometry(Polygon([(465888.877326859, 5079639.436138632), (465885.3413983975, 5079641.524618266), (465882.9542217017, 5079647.166043535), (465888.8780175466, 5079668.703676634), (465888.877326859, 5079639.436138632)]), CRS(32633)) geometry2 = Geometry('POLYGON((-5.13 48, -5.23 48.09, -5.13 48.17, -5.03 48.08, -5.13 48))', CRS.WGS84) cls.test_cases = [ cls.FisTestCase('geometry', FisRequest(layer='TRUE-COLOR-S2-L1C', geometry_list=[geometry1], time=('2017-1-1', '2017-2-1'), resolution="50m", histogram_type=HistogramType.STREAMING, bins=5), raw_result=results[0], result_length=1), cls.FisTestCase('bbox', FisRequest(layer='BANDS-S2-L1C', geometry_list=[bbox], time='2017-1-1', resolution="50m", maxcc=0.2, custom_url_params={ CustomUrlParam.ATMFILTER: "ATMCOR", CustomUrlParam.DOWNSAMPLING: "BICUBIC", CustomUrlParam.UPSAMPLING: "BICUBIC"} ), raw_result=results[1], result_length=1), cls.FisTestCase('list', FisRequest(data_source=DataSource.LANDSAT8, layer='BANDS-L8', geometry_list=[bbox, geometry1], time=('2017-1-1', '2017-1-10'), resolution="100m", bins=32, data_folder=cls.OUTPUT_FOLDER), raw_result=results[2], result_length=2, save_data=True), cls.FisTestCase('Polygon in WGS84', FisRequest(layer='TRUE-COLOR-S2-L1C', geometry_list=[geometry2], time=('2017-10-1', '2017-10-2'), resolution="60m", bins=11, histogram_type=HistogramType.EQUALFREQUENCY), raw_result=results[3], result_length=1), ] for test_case in cls.test_cases: test_case.collect_data()
def _convert_bbox(spatial_extent): crs = spatial_extent.get('crs', 4326) return BBox( (spatial_extent['west'], spatial_extent['south'], spatial_extent['east'], spatial_extent['north'],), CRS(crs), # we support whatever sentinelhub-py supports )
def test_bbox_to_str(self): x1, y1, x2, y2 = 45.0, 12.0, 47.0, 14.0 crs = CRS.WGS84 expect_str = "{},{},{},{}".format(x1, y1, x2, y2) bbox = BBox(((x1, y1), (x2, y2)), crs) self.assertEqual(str(bbox), expect_str, msg="String representations not matching: expected {}, got {}".format( expect_str, str(bbox) ))
def test_bbox_to_resolution(self): bbox = BBox(((111.644, 8.655), (111.7, 8.688)), CRS.WGS84) resx, resy = geo_utils.bbox_to_resolution(bbox, 512, 512) expected_resx = 12.02 expected_resy = 7.15 self.assertAlmostEqual(resx, expected_resx, delta=1E-2, msg='Expected resx {}, got {}'.format(str(expected_resx), str(resx))) self.assertAlmostEqual(resy, expected_resy, delta=1E-2, msg='Expected resy {}, got {}'.format(str(expected_resy), str(resy)))
def bbox(self): if self._bbox == None: self._bbox = BBox( bbox=[ self.coords.x_min, self.coords.y_min, self.coords.x_max, self.coords.y_max ], crs=CRS.WGS84) return self._bbox
def __init__(self, config_path=None): """ :param config_path: Path to configuration file. """ self.config = Config.get_config(config_path) self.bounding_box = BBox(bbox=self.config.bounding_box, crs=CRS.WGS84) self.custom_url_params = { CustomUrlParam.SHOWLOGO: False } # remove SentinelHub logo self._check_access_token()
def test_to_large_request(self): bbox = BBox((-5.23, 48.0, -5.03, 48.17), CRS.WGS84) request = WmsRequest(layer='TRUE-COLOR-S2-L1C', height=6000, width=6000, bbox=bbox, time=('2017-10-01', '2017-10-02')) with self.assertRaises(DownloadFailedException): request.get_data()
def test_bbox_to_repr(self): x1, y1, x2, y2 = 45.0, 12.0, 47.0, 14.0 bbox = BBox(((x1, y1), (x2, y2)), crs=CRS('4326')) expect_repr = "BBox((({}, {}), ({}, {})), crs=CRS('4326'))".format( x1, y1, x2, y2) self.assertEqual( repr(bbox), expect_repr, msg="String representations not matching: expected {}, got {}". format(expect_repr, repr(bbox)))
def test_clipping_wrong_crs(gpkg_file): """Test for trying to clip using different CRS than the data is in""" with pytest.raises(ValueError): feature = FeatureType.VECTOR_TIMELESS, 'lpis_iacs' import_task = VectorImportTask(feature=feature, path=gpkg_file, reproject=False, clip=True) import_task.execute( bbox=BBox([657690, 5071637, 660493, 5074440], CRS.UTM_31N))
def execute(self, eopatch=None, *, filename=None): """ Execute method which adds a new feature to the EOPatch :param eopatch: input EOPatch or None if a new EOPatch should be created :type eopatch: EOPatch or None :param filename: filename of tiff file or None if entire path has already been specified in `folder` parameter of task initialization. :type filename: str or None :return: New EOPatch with added raster layer :rtype: EOPatch """ feature_type, feature_name = next(self.feature()) if eopatch is None: eopatch = EOPatch() with rasterio.open(self._get_file_path(filename)) as source: data_bbox = BBox(source.bounds, CRS(source.crs.to_epsg())) if eopatch.bbox is None: eopatch.bbox = data_bbox reading_window = self._get_reading_window(source.width, source.height, data_bbox, eopatch.bbox) data = source.read(window=reading_window, boundless=True, fill_value=self.no_data_value) if self.image_dtype is not None: data = data.astype(self.image_dtype) if not feature_type.is_spatial(): data = data.flatten() if feature_type.is_timeless(): data = np.moveaxis(data, 0, -1) else: channels = data.shape[0] times = self.timestamp_size if times is None: times = len(eopatch.timestamp) if eopatch.timestamp else 1 if channels % times != 0: raise ValueError( 'Cannot import as a time-dependant feature because the number of tiff image channels ' 'is not divisible by the number of timestamps') data = data.reshape((times, channels // times) + data.shape[1:]) data = np.moveaxis(data, 1, -1) eopatch[feature_type][feature_name] = data return eopatch
def _get_random_bbox(self): lat = self.config.lat_bot_right + ( self.config.lat_top_left - self.config.lat_bot_right) * np.random.ranf(1) lon = self.config.lon_top_left + ( self.config.lon_bot_right - self.config.lon_top_left) * np.random.ranf(1) return BBox( ((lon, lat), (lon + self.config.delta_lon, lat - self.config.delta_lat)), crs=CRS.WGS84)
def _get_task(task_data): window = json.loads(task_data['window']) return Task( task_id=task_data['task_id'], bbox=BBox( bbox=json.loads(task_data['bbox']), # TODO: why is string? crs=CRS(task_data['crs'])), acq_time=dt.datetime.strptime(task_data['datetime'], '%Y-%m-%d'), window_shape=[window['height'], window['width']], data_list=json.loads(task_data['data']), vector_data=task_data['vector_data'])
def sample_image_with_window(image, bbox, window_coords): """ Randomly sample geo-referenced image with a rectangular window """ height = image.shape[0] bbox_coords = list(bbox) resx, resy = get_resolution(image, bbox_coords) return image[height - window_coords[3]: height - window_coords[1], window_coords[0]: window_coords[2], ...], \ BBox([bbox_coords[0] + resx * window_coords[0], bbox_coords[1] + resy * window_coords[1], bbox_coords[0] + resx * window_coords[2], bbox_coords[1] + resy * window_coords[3]], crs=bbox.get_crs())
def test_bbox_from_dict(self): bbox_dict = { 'min_x': 46.07, 'min_y': 13.23, 'max_x': 46.24, 'max_y': 13.57 } bbox = BBox(bbox_dict, CRS.WGS84) self.assertEqual(bbox.upper_right, (46.24, 13.57)) self.assertEqual(bbox.lower_left, (46.07, 13.23)) self.assertEqual(bbox.crs, CRS.WGS84)
def udf_to_eopatch(udf_data): eopatch = EOPatch() for tile in udf_data.raster_collection_tiles: eopatch[(FeatureType.DATA, tile.id)] = tile.data[..., np.newaxis] extent = udf_data.raster_collection_tiles[0].extent bbox = BBox((extent.left, extent.bottom, extent.right, extent.top), CRS.WGS84) eopatch.bbox = bbox return eopatch