def _init_service(self, url: str) -> ArcGISRESTful: service = ArcGISRESTful( url, outformat="json", outfields=self.outfields, crs=self.crs, ) valid_layers = {v.lower(): k for k, v in service.valid_layers.items()} if self.layer not in valid_layers: raise InvalidInputValue("layer", list(valid_layers)) service.layer = valid_layers[self.layer] return service
def test_restful_bysql(): hr = ArcGISRESTful(ServiceURL().restful.nhdplushr, outformat="json") hr.layer = 1 hr.layer = 2 hr.oids_bysql("NHDPLUSID IN (5000500013223, 5000400039708, 5000500004825)") resp_sql = hr.get_features(return_m=True) hr.oids_byfield("NHDPLUSID", [5000500013223, 5000400039708, 5000500004825]) resp_ids = hr.get_features() assert len(resp_sql[0]["features"]) == len(resp_ids[0]["features"])
def test_restful_byid(geometry_nat): wbd2 = ArcGISRESTful(ServiceURL().restful.wbd) wbd2.layer = 1 print(wbd2) wbd2.max_nrecords = 1 wbd2.spatial_relation = "esriSpatialRelIntersects" wbd2.outformat = "geojson" wbd2.featureids = list(range(1, 6)) fields = [f.lower() for f in wbd2.get_validfields()] wbd2.outfields = ["huc2", "name", "areaacres"] huc2 = wbd2.get_features() geom_type = utils.traverse_json(huc2, ["features", "geometry", "type"]) assert (sum(len(h) for h in huc2) == 15 and ["MultiPolygon"] in geom_type and "areaacres" in fields)
def test_restful_bysql(): hr = ArcGISRESTful(ServiceURL().restful.nhdplushr_edits, outformat="json") hr.layer = 1 hr.layer = 2 hr.oids_bysql( "NHDFlowline.PERMANENT_IDENTIFIER IN ('103455178', '103454362', '103453218')" ) resp_sql = hr.get_features(return_m=True) hr.oids_byfield("NHDFlowline.PERMANENT_IDENTIFIER", ["103455178", "103454362", "103453218"]) resp_ids = hr.get_features() assert len(resp_sql[0]["features"]) == len(resp_ids[0]["features"])
def __init__(self, layer: str, outfields: Union[str, List[str]] = "*", crs: str = DEF_CRS): self.service = ArcGISRESTful( ServiceURL().restful.nhdplushr, outformat="json", outfields=outfields, crs=crs, ) valid_layers = self.service.get_validlayers() self.valid_layers = {v.lower(): k for k, v in valid_layers.items()} if layer not in self.valid_layers: raise InvalidInputValue("layer", list(self.valid_layers)) self.service.layer = self.valid_layers[layer] self.outfields = outfields self.crs = crs
def get_bygeom(self, geometry: GTYPE, geo_crs: str) -> gpd.GeoDataFrame: """Retrieve NID data within a geometry. Parameters ---------- geometry : Polygon, MultiPolygon, or tuple of length 4 Geometry or bounding box (west, south, east, north) for extracting the data. geo_crs : list of str The CRS of the input geometry, defaults to epsg:4326. Returns ------- geopandas.GeoDataFrame GeoDataFrame of NID data Examples -------- >>> from pygeohydro import NID >>> nid = NID() >>> dams = nid.get_bygeom((-69.77, 45.07, -69.31, 45.45), "epsg:4326") >>> print(dams.name.iloc[0]) Little Moose """ _geometry = geoutils.geo2polygon(geometry, geo_crs, DEF_CRS) wbd = ArcGISRESTful( ServiceURL().restful.wbd, 4, outformat="json", outfields="huc8", expire_after=self.expire_after, disable_caching=self.disable_caching, ) resp = wbd.get_features(wbd.oids_bygeom(_geometry), return_geom=False) huc_ids = [ tlz.get_in(["attributes", "huc8"], i) for r in resp for i in tlz.get_in(["features"], r) ] dams = self.get_byfilter([{"huc8": huc_ids}])[0] return dams[dams.within(_geometry)].copy()
def test_restful_bymultipoint(): url = "https://watersgeo.epa.gov/arcgis/rest/services/NHDPlus/NHDPlus/MapServer" sql_clause = "FTYPE NOT IN (420,428,566)" geom = [ (-97.06138, 32.837), (-97.06133, 32.836), (-97.06124, 32.834), (-97.06127, 32.832), ] geo_crs = "epsg:4269" distance = 1500 service = ArcGISRESTful(url, outformat="json") service.layer = 2 # network flowline service.oids_bygeom(geom, geo_crs=geo_crs, sql_clause=sql_clause, distance=distance) resp = service.get_features(return_m=True) assert len(resp[0]["features"]) == 3
class NHDPlusHR: """Access NHDPlus HR database through the National Map ArcGISRESTful. Parameters ---------- layer : str A valid service layer. For a list of available layers pass an empty string to the class. outfields : str or list, optional Target field name(s), default to "*" i.e., all the fileds. crs : str, optional Target spatial reference, default to EPSG:4326 """ def __init__(self, layer: str, outfields: Union[str, List[str]] = "*", crs: str = DEF_CRS): self.service = ArcGISRESTful( ServiceURL().restful.nhdplushr, outformat="json", outfields=outfields, crs=crs, ) valid_layers = self.service.get_validlayers() self.valid_layers = {v.lower(): k for k, v in valid_layers.items()} if layer not in self.valid_layers: raise InvalidInputValue("layer", list(self.valid_layers)) self.service.layer = self.valid_layers[layer] self.outfields = outfields self.crs = crs def bygeom( self, geom: Union[Polygon, Tuple[float, float, float, float]], geo_crs: str = "epsg:4326", sql_clause: str = "", return_m: bool = False, ) -> gpd.GeoDataFrame: """Get feature within a geometry that can be combined with a SQL where clause. Parameters ---------- geom : Polygon or tuple A geometry (Polgon) or bounding box (tuple of length 4). geo_crs : str The spatial reference of the input geometry. sql_clause : str, optional A valid SQL 92 WHERE clause, defaults to an empty string. return_m : bool Whether to activate the Return M (measure) in the request, defaults to False. Returns ------- geopandas.GeoDataFrame The requested features as a GeoDataFrame. """ self.service.oids_bygeom(geom, geo_crs=geo_crs, sql_clause=sql_clause) return self._getfeatures(return_m) def byids(self, field: str, fids: Union[str, List[str]], return_m: bool = False) -> gpd.GeoDataFrame: """Get features based on a list of field IDs. Parameters ---------- field : str Name of the target field that IDs belong to. fids : str or list A list of target field ID(s). return_m : bool Whether to activate the Return M (measure) in the request, defaults to False. Returns ------- geopandas.GeoDataFrame The requested features as a GeoDataFrame. """ self.service.oids_byfield(field, fids) return self._getfeatures(return_m) def bysql(self, sql_clause: str, return_m: bool = False) -> gpd.GeoDataFrame: """Get feature IDs using a valid SQL 92 WHERE clause. Notes ----- Not all web services support this type of query. For more details look `here <https://developers.arcgis.com/rest/services-reference/query-feature-service-.htm#ESRI_SECTION2_07DD2C5127674F6A814CE6C07D39AD46>`__ Parameters ---------- sql_clause : str A valid SQL 92 WHERE clause. return_m : bool Whether to activate the Return M (measure) in the request, defaults to False. Returns ------- geopandas.GeoDataFrame The requested features as a GeoDataFrame. """ self.service.oids_bysql(sql_clause) return self._getfeatures(return_m) def _getfeatures(self, return_m: bool = False): """Send a request for getting data based on object IDs. Parameters ---------- return_m : bool Whether to activate the Return M (measure) in the request, defaults to False. Returns ------- geopandas.GeoDataFrame The requested features as a GeoDataFrame. """ resp = self.service.get_features(return_m) return geoutils.json2geodf(resp)
def test_restful_bygeom(geometry_nat): wbd8 = ArcGISRESTful(f"{ServiceURL().restful.wbd}/4") wbd8.n_threads = 4 wbd8.oids_bygeom(geometry_nat.bounds) wbd8.oids_bygeom(geometry_nat) huc8_all = wbd8.get_features() wbd8.oids_bygeom(geometry_nat, sql_clause="areasqkm > 5000") huc8_large = wbd8.get_features() assert len(huc8_all[0]["features"]) - len(huc8_large[0]["features"]) == 2
def test_restful_bygeom(geometry_nat): geofab = ArcGISRESTful(f"{ServiceURL().restful.nhd_fabric}/1") geofab.n_threads = 4 geofab.oids_bygeom(geometry_nat.bounds) geofab.oids_bygeom(geometry_nat) wb_all = geofab.get_features() geofab.oids_bygeom(geometry_nat, sql_clause="areasqkm > 20") wb_large = geofab.get_features() assert len(wb_all[0]["features"]) - len(wb_large[0]["features"]) == 915