def shpext_to_boundary(in_shp, out_srs=None): """ Read one feature class extent and create a boundary with that extent """ from gasp.gt.prop.ext import get_ext from gasp.g.to import create_polygon # Get Extent ext = get_ext(in_shp) # Create points of the new boundary based on the extent boundary_points = [(ext[0], ext[3]), (ext[1], ext[3]), (ext[1], ext[2]), (ext[0], ext[2]), (ext[0], ext[3])] polygon = create_polygon(boundary_points) if out_srs: from gasp.gt.prop.prj import get_epsg_shp in_srs = get_epsg_shp(in_shp) if in_srs != out_srs: from gasp.g.prj import prj_ogrgeom poly = prj_ogrgeom(polygon, in_srs, out_srs, api='shply') return poly else: return polygon else: return polygon
def get_ext(inFile, outEpsg=None): """ Get Extent of any GIS Data return None if inFile is not a GIS File """ from gasp.gt.prop.ff import check_isRaster, check_isShp if check_isRaster(inFile): from gasp.gt.prop.rst import rst_ext extent = rst_ext(inFile) else: if check_isShp(inFile): from gasp.gt.prop.feat import get_ext as gext extent = gext(inFile) else: return None if outEpsg: from gasp.gt.prop.prj import get_epsg fileEpsg = get_epsg(inFile) if not fileEpsg: raise ValueError('cannot get EPSG of input file') if fileEpsg != outEpsg: from gasp.g.to import new_pnt from gasp.g.prj import prj_ogrgeom bt_left = prj_ogrgeom(new_pnt(extent[0], extent[2]), fileEpsg, outEpsg) top_right = prj_ogrgeom(new_pnt(extent[1], extent[3]), fileEpsg, outEpsg) left, bottom = bt_left.GetX(), bt_left.GetY() right, top = top_right.GetX(), top_right.GetY() extent = [left, right, bottom, top] return extent
def bf_prop(buffer_shp, epsg_in, isFile=None): """ Return the centroid and radius distance of one buffer geometry Centroid X, Y in the units of the buffer_shp; Radius in meters. Object return will be something like this: o = { 'X': x_value, 'Y': y_value, 'R': radius_value } """ from gasp.gt.prop.feat import get_cntr_bnd if isFile: from gasp.gt.attr import geom_by_idx BUFFER_GEOM = ogr.CreateGeometryFromWkt(geom_by_idx(buffer_shp, 0)) else: BUFFER_GEOM = ogr.CreateGeometryFromWkt(buffer_shp) # Get x_center, y_center and dist from polygon geometry # TODO: Besides 4326, we need to include also the others geographic systems if int(epsg_in) == 4326: from gasp.g.prj import prj_ogrgeom BUFFER_GEOM_R = prj_ogrgeom(BUFFER_GEOM, epsg_in, 3857) else: BUFFER_GEOM_R = BUFFER_GEOM dist = get_buffer_radius(BUFFER_GEOM_R.ExportToWkt(), isFile=None) center = get_cntr_bnd(BUFFER_GEOM, isFile=None) return {'X': center.GetX(), 'Y': center.GetY(), 'R': dist}
def coords_to_boundary(topLeft, lowerRight, epsg, outEpsg=None): """ Top Left and Lower Right to Boundary """ from osgeo import ogr from gasp.g.to import create_polygon boundary_points = [(topLeft[0], topLeft[1]), (lowerRight[0], topLeft[1]), (lowerRight[0], lowerRight[1]), (topLeft[0], lowerRight[1]), (topLeft[0], topLeft[1])] # Create polygon polygon = create_polygon(boundary_points) # Convert SRS if outEPSG if outEpsg and epsg != outEpsg: from gasp.g.prj import prj_ogrgeom poly = prj_ogrgeom(polygon, epsg, outEpsg) return poly else: return polygon
def getBufferParam(inArea, inAreaSRS, outSRS=4326): """ Get Buffer X, Y Center and radius in any SRS (radius in meteres). Check the type of the 'inArea' Object and return the interest values. inArea could be a file, dict, list or tuple """ import os from osgeo import ogr from gasp.g.to import new_pnt from gasp.g.prj import prj_ogrgeom TYPE = type(inArea) if TYPE == str: # Assuming that inArea is a file # Check if exists if os.path.exists(inArea): if os.path.isfile(inArea): from gasp.gt.attr import geom_by_idx # Get Geometry object BUFFER_GEOM = geom_by_idx(inArea, 0) # To outSRS if int(inAreaSRS) != outSRS: BUFFER_GEOM = prj_ogrgeom( ogr.CreateGeometryFromWkt(BUFFER_GEOM), inAreaSRS, outSRS).ExportToWkt() # Get x_center, y_center and radius xyr = bf_prop(BUFFER_GEOM, outSRS, isFile=None) x_center, y_center, dist = str(xyr['X']), str(xyr['Y']), str( xyr['R']) else: raise ValueError('The given path exists but it is not a file') else: raise ValueError('The given path doesn\'t exist') elif TYPE == dict: X = 'x' if 'x' in inArea else 'X' if 'X' in inArea else \ 'lng' if 'lng' in inArea else None Y = 'y' if 'x' in inArea else 'Y' if 'Y' in inArea else \ 'lat' if 'lat' in inArea else None R = 'r' if 'r' in inArea else 'R' if 'R' in inArea else \ 'rad' if 'rad' in inArea else 'RADIUS' if 'RADIUS' in inArea \ else 'radius' if 'radius' in inArea else None if not X or not Y or not R: raise ValueError( ('The keys used to identify the buffer properties ' 'are not valid! ' 'Please choose one of the following keys groups: ' 'x, y, r; ' 'X, Y, R; ' 'lat, lng, rad')) else: x_center, y_center, dist = (str(inArea[X]), str(inArea[Y]), str(inArea[R])) if inAreaSRS != outSRS: pnt_wgs = prj_ogrgeom(new_pnt(x_center, y_center), inAreaSRS, outSRS) x_center, y_center = (pnt_wgs.GetX(), pnt_wgs.GetY()) elif TYPE == list or TYPE == tuple: x_center, y_center, dist = inArea if inAreaSRS != outSRS: pnt_wgs = prj_ogrgeom(new_pnt(x_center, y_center), inAreaSRS, outSRS) x_center, y_center = (pnt_wgs.GetX(), pnt_wgs.GetY()) else: raise ValueError( ('Please give a valid path to a shapefile or a tuple, dict or ' 'list with the x, y and radius values')) return x_center, y_center, dist
def geotweets_location(inGeom, epsg_in, keyword=None, epsg_out=4326, onlySearchAreaContained=True, keyToUse=None): """ Search data in Twitter and array with that data inGeom cloud be a shapefile with a single buffer feature or a dict like: inGeom = { x: x_value, y: y_value, r: dist (in meters) } or a list or a tuple: inGeom = [x, y, radius] """ from shapely.geometry import Polygon, Point from geopandas import GeoDataFrame from gasp.gt.prop.feat.bf import getBufferParam x_center, y_center, dist = getBufferParam(inGeom, epsg_in, outSRS=4326) # Extract data from Twitter data = search_tweets(lat=y_center, lng=x_center, radius=float(dist) / 1000, keyword=keyword, NR_ITEMS=500, only_geo=True, key=keyToUse) try: if not data: return 0 except: pass # Pandas to GeoPandas geoms = [Point(xy) for xy in zip(data.longitude, data.latitude)] data.drop(["latitude", "longitude"], axis=1, inplace=True) gdata = GeoDataFrame(data, crs={'init': 'epsg:4326'}, geometry=geoms) if onlySearchAreaContained: from shapely.wkt import loads from gasp.g.prj import prj_ogrgeom from gasp.g.gop.prox import xy_to_buffer # Check if all retrieve points are within the search area _x_center, _y_center, _dist = getBufferParam(inGeom, epsg_in, outSRS=3857) search_area = xy_to_buffer(float(_x_center), float(_y_center), float(_dist)) search_area = prj_ogrgeom(search_area, 3857, 4326) search_area = loads(search_area.ExportToWkt()) gdata["tst_geom"] = gdata["geometry"].intersects(search_area) gdata = gdata[gdata["tst_geom"] == True] gdata.reset_index(drop=True, inplace=True) gdata.drop("tst_geom", axis=1, inplace=True) if epsg_out != 4326: gdata = gdata.to_crs({'init': 'epsg:{}'.format(str(epsg_out))}) return gdata
def photos_location(buffer_shp, epsg_in, keyword=None, epsg_out=4326, onlySearchAreaContained=True, keyToUse=None): """ Search for data in Flickr and return a array with the same data buffer_shp cloud be a shapefile with a single buffer feature or a dict like: buffer_shp = { x: x_value, y: y_value, r: dist (in meters) } or a list or a tuple: buffer_shp = [x, y, radius] """ import pandas from shapely.geometry import Polygon, Point from shapely.wkt import loads from geopandas import GeoDataFrame from gasp.g.gop.prox import xy_to_buffer from gasp.gt.prop.feat.bf import getBufferParam from gasp.g.prj import prj_ogrgeom x_center, y_center, dist = getBufferParam(buffer_shp, epsg_in, outSRS=4326) # Retrive data from Flickr photos = search_photos(lat=y_center, lng=x_center, radius=float(dist) / 1000, keyword=keyword, apiKey=keyToUse) try: if not photos: # Return noData return 0 except: pass photos['longitude'] = photos['longitude'].astype(float) photos['latitude'] = photos['latitude'].astype(float) geoms = [Point(xy) for xy in zip(photos.longitude, photos.latitude)] gdata = GeoDataFrame(photos, crs={'init': 'epsg:4326'}, geometry=geoms) if onlySearchAreaContained: _x_center, _y_center, _dist = getBufferParam(buffer_shp, epsg_in, outSRS=3857) # Check if all retrieve points are within the search area search_area = xy_to_buffer(float(_x_center), float(_y_center), float(_dist)) search_area = prj_ogrgeom(search_area, 3857, 4326) search_area = loads(search_area.ExportToWkt()) gdata["tst_geom"] = gdata["geometry"].intersects(search_area) gdata = gdata[gdata["tst_geom"] == True] gdata.reset_index(drop=True, inplace=True) gdata["fid"] = gdata["id"] if "url_l" in gdata.columns.values: gdata["url"] = gdata["url_l"] else: gdata["url"] = 'None' gdata["description"] = gdata["_content"] # Drop irrelevant fields cols = list(gdata.columns.values) delCols = [] for col in cols: if col != 'geometry' and col != 'description' and \ col != 'fid' and col != 'url' and col != 'datetaken' \ and col != 'dateupload' and col != 'title': delCols.append(col) else: continue gdata.drop(delCols, axis=1, inplace=True) if epsg_out != 4326: gdata = gdata.to_crs({'init': 'epsg:{}'.format(str(epsg_out))}) return gdata
def ext_to_rst(topLeft, btRight, outRst, cellsize=None, epsg=None, outEpsg=None, invalidResultAsNull=None): """ Extent to Raster """ import os import numpy from osgeo import ogr, gdal from gasp.gt.prop.ff import drv_name left, top = topLeft right, bottom = btRight cellsize = 10 if not cellsize else cellsize if outEpsg and epsg and outEpsg != epsg: from gasp.g.to import new_pnt from gasp.g.to import create_polygon from gasp.g.prj import prj_ogrgeom extGeom = prj_ogrgeom( create_polygon([ new_pnt(left, top), new_pnt(right, top), new_pnt(right, bottom), new_pnt(left, bottom), new_pnt(left, top) ]), epsg, outEpsg) left, right, bottom, top = extGeom.GetEnvelope() # Get row and cols number rows = (float(top) - float(bottom)) / cellsize cols = (float(right) - float(left)) / cellsize rows = int(rows) if rows == int(rows) else int(rows) + 1 cols = int(cols) if cols == int(cols) else int(cols) + 1 if not invalidResultAsNull: NEW_RST_ARRAY = numpy.zeros((rows, cols)) else: try: NEW_RST_ARRAY = numpy.zeros((rows, cols)) except: return None # Create new Raster img = gdal.GetDriverByName(drv_name(outRst)).Create( outRst, cols, rows, 1, gdal.GDT_Byte) img.SetGeoTransform((left, cellsize, 0, top, 0, -cellsize)) band = img.GetRasterBand(1) band.WriteArray(NEW_RST_ARRAY) if epsg: from osgeo import osr rstSrs = osr.SpatialReference() rstSrs.ImportFromEPSG(epsg) img.SetProjection(rstSrs.ExportToWkt()) band.FlushCache() return outRst
def download_by_boundary(input_boundary, folder_out, osm_name, epsg, GetUrl=True, db_name=None, geomCol=None, justOneFeature=None): """ Download data from OSM using a bounding box """ import os from osgeo import ogr from gasp.to.web import get_file from gasp.pyt.oss import os_name OS_NAME = os_name() EXTENTS = [] if db_name and geomCol: """ Assuming input_boundary is a PostgreSQL Table """ from gasp.pyt import obj_to_lst from gasp.gql.prop import tbl_ext for t in obj_to_lst(input_boundary): EXTENTS.append(tbl_ext(db_name, t, geomCol)) else: if type(input_boundary) == dict: if 'top' in input_boundary and 'bottom' in input_boundary \ and 'left' in input_boundary and 'right' in input_boundary: EXTENTS.append([ input_boundary['left'],input_boundary['right'], input_boundary['bottom'], input_boundary['top'] ]) else: raise ValueError(( 'input_boundary is a dict but the keys are not correct. ' 'Please use left, right, top and bottom as keys' )) elif type(input_boundary) == list: if len(input_boundary) == 4: EXTENTS.append(input_boundary) else: raise ValueError(( 'input boundary is a list with more than 4 objects. ' 'The list should be like: ' 'l = [left, right, bottom, top]' )) elif type(input_boundary) == ogr.Geometry: EXTENTS.append(input_boundary.GetEnvelope()) else: # Assuming input boundary is a file #Check if file exists if not os.path.exists(input_boundary): raise ValueError(( "Sorry, but the file {} does not exist inside the folder {}!" ).format( os.path.basename(input_boundary), os.path.dirname(input_boundary) )) # Check if is a raster from gasp.gt.prop.ff import check_isRaster isRst = check_isRaster(input_boundary) # Get EPSG if not epsg: from gasp.gt.prop.prj import get_epsg epsg = get_epsg(input_boundary) if isRst: from gasp.gt.prop.rst import rst_ext # Get raster extent EXTENTS.append(rst_ext(input_boundary)) else: from gasp.gt.prop.ff import drv_name # Todo: check if it is shape # Open Dataset inSrc = ogr.GetDriverByName(drv_name( input_boundary)).Open(input_boundary) lyr = inSrc.GetLayer() i = 1 for feat in lyr: geom = feat.GetGeometryRef() featext = geom.GetEnvelope() EXTENTS.append(featext) if justOneFeature: break if epsg != 4326: from gasp.g.to import new_pnt from gasp.g.prj import prj_ogrgeom for i in range(len(EXTENTS)): bottom_left = prj_ogrgeom(new_pnt( EXTENTS[i][0], EXTENTS[i][2]), epsg, 4326) top_right = prj_ogrgeom(new_pnt( EXTENTS[i][1], EXTENTS[i][3]), epsg, 4326) left , bottom = bottom_left.GetX(), bottom_left.GetY() right, top = top_right.GetX() , top_right.GetY() EXTENTS[i] = [left, right, bottom, top] #url = "https://overpass-api.de/api/map?bbox={}" url = "https://lz4.overpass-api.de/api/interpreter?bbox={}" RESULTS = [] for e in range(len(EXTENTS)): bbox_str = ','.join([str(p) for p in EXTENTS[e]]) if GetUrl: RESULTS.append(url.format(bbox_str)) continue if len(EXTENTS) == 1: outOsm = os.path.join(folder_out, osm_name + '.xml') else: outOsm = os.path.join(folder_out, "{}_{}.xml".format(osm_name, str(e))) osm_file = get_file( url.format(bbox_str), outOsm, useWget=None if OS_NAME == 'Windows' else None ) RESULTS.append(osm_file) return RESULTS[0] if len(RESULTS) == 1 else RESULTS