def visualize_spatial_extent(self, extent_type, spat_extent): """Default visualization of spatial extent""" world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) f, ax = plt.subplots(1, figsize=(12, 6)) world.plot(ax=ax, facecolor="lightgray", edgecolor="gray") geospatial.geodataframe(extent_type, spat_extent).plot(ax=ax, color="#FF8C00", alpha=0.7) plt.show()
def visualize_spatial_extent( self, ): # additional args, basemap, zoom level, cmap, export """ Creates a map displaying the input spatial extent Examples -------- >>> reg_a = ipx.Query('ATL06','path/spatialfile.shp',['2019-02-22','2019-02-28']) # doctest: +SKIP >>> reg_a.visualize_spatial_extent # doctest: +SKIP [visual map output] """ gdf = geospatial.geodataframe(self.extent_type, self._spat_extent) try: from shapely.geometry import Polygon import geoviews as gv gv.extension("bokeh") line_geoms = Polygon(gdf["geometry"][0]).boundary bbox_poly = gv.Path(line_geoms).opts(color="red", line_color="red") tile = gv.tile_sources.EsriImagery.opts(width=500, height=500) return tile * bbox_poly except ImportError: world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) f, ax = plt.subplots(1, figsize=(12, 6)) world.plot(ax=ax, facecolor="lightgray", edgecolor="gray") gdf.plot(ax=ax, color="#FF8C00", alpha=0.7) plt.show()
def test_gdf_from_bbox(): obs = geospatial.geodataframe('bounding_box', [-55, 68, -48, 71]) geom = [ Polygon(list(zip([-55, -55, -48, -48, -55], [68, 71, 71, 68, 68]))) ] exp = gpd.GeoDataFrame(geometry=geom) #DevNote: this feels like a questionable test to me, since it specifies the first entry (though there should only be one) assert obs.geometry[0] == exp.geometry[0]
def visualize_spatial_extent( self): #additional args, basemap, zoom level, cmap, export """ Creates a map displaying the input spatial extent Examples -------- >>> icepyx.icesat2data.Icesat2Data('ATL06','path/spatialfile.shp',['2019-02-22','2019-02-28']) >>> reg_a.visualize_spatial_extent [visual map output] """ world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) f, ax = plt.subplots(1, figsize=(12, 6)) world.plot(ax=ax, facecolor='lightgray', edgecolor='gray') geospatial.geodataframe(self.extent_type, self._spat_extent).plot(ax=ax, color='#FF8C00', alpha=0.7) plt.show()
def spatial(spatial_extent): """ Validate the input spatial extent and return the needed parameters to the query object. """ if isinstance(spatial_extent, list): # bounding box if len(spatial_extent) == 4 and all( type(i) in [int, float] for i in spatial_extent): assert -90 <= spatial_extent[1] <= 90, "Invalid latitude value" assert -90 <= spatial_extent[3] <= 90, "Invalid latitude value" assert ( -180 <= spatial_extent[0] <= 180 ), "Invalid longitude value" # tighten these ranges depending on actual allowed inputs assert -180 <= spatial_extent[2] <= 180, "Invalid longitude value" if np.sign(spatial_extent[0]) != np.sign(spatial_extent[2]): assert (spatial_extent[0] >= spatial_extent[2]), "Invalid bounding box longitudes" else: assert (spatial_extent[0] <= spatial_extent[2]), "Invalid bounding box longitudes" assert (spatial_extent[1] <= spatial_extent[3]), "Invalid bounding box latitudes" _spat_extent = spatial_extent extent_type = "bounding_box" # user-entered polygon as list of lon, lat coordinate pairs elif all(type(i) in [list, tuple] for i in spatial_extent): assert (len(spatial_extent) >= 4), "Your spatial extent polygon has too few vertices" assert (spatial_extent[0][0] == spatial_extent[-1][0] ), "Starting longitude doesn't match ending longitude" assert (spatial_extent[0][1] == spatial_extent[-1][1] ), "Starting latitude doesn't match ending latitude" polygon = (",".join([str(c) for xy in spatial_extent for c in xy])).split(",") extent_type = "polygon" polygon = [float(i) for i in polygon] gdf = geospatial.geodataframe(extent_type, polygon, file=False) _spat_extent = gdf.iloc[0].geometry # _spat_extent = polygon # extent_type = 'polygon' # #DevGoal: properly format this input type (and any polygon type) so that it is clockwise (and only contains 1 pole)!! # warnings.warn("this type of input is not yet well handled and you may not be able to find data") # user-entered polygon as a single list of lon and lat coordinates elif all(type(i) in [int, float] for i in spatial_extent): assert (len(spatial_extent) >= 8), "Your spatial extent polygon has too few vertices" assert ( len(spatial_extent) % 2 == 0 ), "Your spatial extent polygon list should have an even number of entries" assert (spatial_extent[0] == spatial_extent[-2] ), "Starting longitude doesn't match ending longitude" assert (spatial_extent[1] == spatial_extent[-1] ), "Starting latitude doesn't match ending latitude" extent_type = "polygon" polygon = [float(i) for i in spatial_extent] gdf = geospatial.geodataframe(extent_type, polygon, file=False) _spat_extent = gdf.iloc[0].geometry # _spat_extent = polygon else: raise ValueError( "Your spatial extent does not meet minimum input criteria") # DevGoal: write a test for this? # make sure there is nothing set to _geom_filepath since its existence determines later steps try: del _geom_filepath except: UnboundLocalError # DevGoal: revisit this section + geospatial.geodataframe. There might be some good ways to combine the functionality in these checks with that elif isinstance(spatial_extent, str): assert os.path.exists( spatial_extent ), "Check that the path and filename of your geometry file are correct" # DevGoal: more robust polygon inputting (see Bruce's code): correct for clockwise/counterclockwise coordinates, deal with simplification, etc. if spatial_extent.split(".")[-1] in ["kml", "shp", "gpkg"]: extent_type = "polygon" gdf = geospatial.geodataframe(extent_type, spatial_extent, file=True) # print(gdf.iloc[0].geometry) # DevGoal: does the below line mandate that only the first polygon will be read? Perhaps we should require files containing only one polygon? # RAPHAEL - It only selects the first polygon if there are multiple. Unless we can supply the CMR params with muliple polygon inputs we should probably req a single polygon. _spat_extent = gdf.iloc[0].geometry # _spat_extent = apifmt._fmt_polygon(spatial_extent) _geom_filepath = spatial_extent else: raise TypeError( "Input spatial extent file must be a kml, shp, or gpkg") # DevGoal: currently no specific test for this if statement... if "_geom_filepath" not in locals(): _geom_filepath = None return extent_type, _spat_extent, _geom_filepath
def test_bad_extent_input(): ermsg = "Your spatial extent type is not an accepted input and a geodataframe cannot be constructed" #DevNote: can't get the test to pass if the extent_type is included. Not sure why the strings "don't match" # ermsg = "Your spatial extent type (polybox) is not an accepted input and a geodataframe cannot be constructed" with pytest.raises(TypeError, match=ermsg): geospatial.geodataframe('polybox', [1, 2, 3, 4])