def feat_to_pnt(inShp, outPnt, epsg=None): """ Get Centroid from each line in a PolyLine Feature Class """ import os from osgeo import ogr from gasp.gt.prop.ff import drv_name from gasp.g.lyr.fld import copy_flds from gasp.gt.prop.feat import lst_fld # TODO: check if geometry is correct # Open data polyData = ogr.GetDriverByName(drv_name(outPnt)).Open(inShp) polyLyr = polyData.GetLayer() # Get SRS for the output if not epsg: from gasp.gt.prop.prj import get_shp_sref srs = get_shp_sref(polyLyr) else: from gasp.gt.prop.prj import get_sref_from_epsg srs = get_sref_from_epsg(epsg) # Create output pntData = ogr.GetDriverByName(drv_name(outPnt)).CreateDataSource(outPnt) pntLyr = pntData.CreateLayer(os.path.splitext(os.path.basename(outPnt))[0], srs, geom_type=ogr.wkbPoint) # Copy fields from input to output fields = lst_fld(polyLyr) copy_flds(polyLyr, pntLyr) pntLyrDefn = pntLyr.GetLayerDefn() for feat in polyLyr: geom = feat.GetGeometryRef() pnt = geom.Centroid() new_feat = ogr.Feature(pntLyrDefn) new_feat.SetGeometry(pnt) for fld in fields: new_feat.SetField(fld, feat.GetField(fld)) pntLyr.CreateFeature(new_feat) new_feat.Destroy() del pntLyr del polyLyr pntData.Destroy() polyData.Destroy() return outPnt
def pnts_to_boundary(pntShp, outBound, distMeters): """ Create a boundary from Point using a tolerance in meters """ from osgeo import ogr from gasp.pyt.oss import fprop from gasp.gt.prop.ff import drv_name from gasp.g.to import new_pnt from gasp.gt.prop.prj import get_shp_sref SRS = get_shp_sref(pntShp) shp = ogr.GetDriverByName(drv_name(pntShp)).Open(pntShp) lyr = shp.GetLayer() outShp = ogr.GetDriverByName(drv_name(outBound)).CreateDataSource(outBound) outLyr = outShp.CreateLayer( fprop(outBound, 'fn', forceLower=True), SRS, geom_type=ogr.wkbPolygon ) outDefn = outLyr.GetLayerDefn() for feat in lyr: __feat = ogr.Feature(outDefn) ring = ogr.Geometry(ogr.wkbLinearRing) geom = feat.GetGeometryRef() X, Y = geom.GetX(), geom.GetY() boundary_points = [ new_pnt(X - distMeters, Y + distMeters), # Topleft new_pnt(X + distMeters, Y + distMeters), # TopRight new_pnt(X + distMeters, Y - distMeters), # Lower Right new_pnt(X - distMeters, Y - distMeters), # Lower Left new_pnt(X - distMeters, Y + distMeters) ] for pnt in boundary_points: ring.AddPoint(pnt.GetX(), pnt.GetY()) polygon = ogr.Geometry(ogr.wkbPolygon) polygon.AddGeometry(ring) __feat.SetGeometry(polygon) outLyr.CreateFeature(__feat) feat.Destroy() __feat = None ring = None polygon = None shp.Destroy() outShp.Destroy() return outBound
def sel_by_loc(shp, boundary_filter, filtered_output): """ Filter a shp using the location of a boundary_filter shp For now the boundary must have only one feature Writes the filter on a new shp """ import os from osgeo import ogr from gasp.gt.prop.ff import drv_name from gasp.gt.prop.feat import get_gtype from gasp.g.lyr.fld import copy_flds from gasp.gt.toshp import copy_feat from gasp.pyt.oss import fprop # Open main data dtSrc = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = dtSrc.GetLayer() # Get filter geom filter_shp = ogr.GetDriverByName(drv_name(boundary_filter)).Open( boundary_filter, 0) filter_lyr = filter_shp.GetLayer() c = 0 for f in filter_lyr: if c: break geom = f.GetGeometryRef() c += 1 filter_shp.Destroy() # Apply filter lyr.SetSpatialFilter(geom) # Copy filter objects to a new shape out = ogr.GetDriverByName( drv_name(filtered_output)).CreateDataSource(filtered_output) outLyr = out.CreateLayer(fprop(filtered_output, 'fn'), geom_type=get_gtype(shp, gisApi='ogr', name=None, py_cls=True)) # Copy fields copy_flds(lyr, outLyr) copy_feat(lyr, outLyr, outDefn=outLyr.GetLayerDefn(), only_geom=False, gisApi='ogrlyr')
def get_cntr_bnd(shp, isFile=None): """ Return centroid (OGR Point object) of a Boundary (layer with a single feature). """ from osgeo import ogr from gasp.gt.prop.ff import drv_name if isFile: shp = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = shp.GetLayer() feat = lyr[0] geom = feat.GetGeometryRef() else: geom = shp centroid = geom.Centroid() cnt = ogr.CreateGeometryFromWkt(centroid.ExportToWkt()) shp.Destroy() return cnt
def lst_fld(shp): """ Return a list with every field name in a vectorial layer """ from osgeo import ogr from gasp.gt.prop.ff import drv_name if type(shp) == ogr.Layer: lyr = shp c = 0 else: data = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = data.GetLayer() c = 1 defn = lyr.GetLayerDefn() fields = [] for i in range(0, defn.GetFieldCount()): fdefn = defn.GetFieldDefn(i) fields.append(fdefn.name) if c: del lyr data.Destroy() return fields
def rst_val_to_points(pnt, rst): """ Extract, for a given point dataset, the value of a cell with the same location Returns a dict: d = { fid: value, ... } """ from osgeo import ogr, gdal from gasp.gt.prop.ff import drv_name values_by_point = {} shp = ogr.GetDriverByName(drv_name(pnt)).Open(pnt, 0) lyr = shp.GetLayer() img = gdal.Open(rst) geo_transform = img.GetGeoTransform() band = img.GetRasterBand(1) for feat in lyr: geom = feat.GetGeometryRef() mx, my = geom.GetX(), geom.GetY() px = int((mx - geo_transform[0]) / geo_transform[1]) py = int((my - geo_transform[3]) / geo_transform[5]) val_pix = band.ReadAsArray(px, py, 1, 1) values_by_point[int(feat.GetFID())] = float(val_pix[0][0]) return values_by_point
def area_to_dic(shp): """ Return the following output: dic = { id_feat: area, ..., id_feat: area } """ from osgeo import ogr from gasp.gt.prop.ff import drv_name o = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) l = o.GetLayer() d = {} c = 0 for feat in l: g = feat.GetGeometryRef() area = g.GetArea() d[c] = area c += 1 del l o.Destroy() return d
def geom_by_idx(inShp, idx): """ Get Geometry by index in file """ from osgeo import ogr from gasp.gt.prop.ff import drv_name src = ogr.GetDriverByName(drv_name(inShp)).Open(inShp) lyr = src.GetLayer() c = 0 geom = None for f in lyr: if idx == c: geom = f.GetGeometryRef() else: c += 1 if not geom: raise ValueError("inShp has not idx") _geom = geom.ExportToWkt() del lyr src.Destroy() return _geom
def ogr_list_fields_defn(shp): """ Return a dict with the field name as key and the field definition as value Field defn is the same of saying name + type """ if type(shp) == ogr.Layer: lyr = shp c = 0 else: data = ogr.GetDriverByName( drv_name(shp)).Open(shp, 0) lyr = data.GetLayer() c = 1 defn = lyr.GetLayerDefn() fields = {} for i in range(0, defn.GetFieldCount()): fdefn = defn.GetFieldDefn(i) fieldType = fdefn.GetFieldTypeName(fdefn.GetType()) fields[fdefn.name] = {fdefn.GetType(): fieldType} if c: del lyr data.Destroy() return fields
def get_shp_sref(shp): """ Get Spatial Reference Object from Feature Class/Lyr """ from osgeo import ogr from gasp.gt.prop.ff import drv_name if type(shp) == ogr.Layer: lyr = shp c = 0 else: data = ogr.GetDriverByName(drv_name(shp)).Open(shp) lyr = data.GetLayer() c = 1 spref = lyr.GetSpatialRef() if c: del lyr data.Destroy() return spref
def obj_to_rst(inArray, outRst, template, noData=None, geotrans=None): """ Send Array to Raster API Available: * gdal; """ gisApi = 'gdal' if gisApi == 'gdal': from osgeo import gdal, osr, gdal_array from gasp.gt.prop.ff import drv_name from gasp.gt.prop.rst import compress_option if type(template).__name__ == 'Dataset': img_template = template else: img_template = gdal.Open(template) geo_transform = img_template.GetGeoTransform() if not geotrans else \ geotrans rows, cols = inArray.shape drv_n = drv_name(outRst) driver = gdal.GetDriverByName(drv_n) c_opt = compress_option(drv_n) if c_opt: out = driver.Create(outRst, cols, rows, 1, gdal_array.NumericTypeCodeToGDALTypeCode( inArray.dtype), options=[c_opt]) else: out = driver.Create( outRst, cols, rows, 1, gdal_array.NumericTypeCodeToGDALTypeCode(inArray.dtype)) out.SetGeoTransform(geo_transform) outBand = out.GetRasterBand(1) if noData: outBand.SetNoDataValue(noData) outBand.WriteArray(inArray) proj = osr.SpatialReference(wkt=img_template.GetProjection()) if proj: out.SetProjection(img_template.GetProjection()) outBand.FlushCache() else: raise ValueError('The api {} is not available'.format(gisApi)) return outRst
def statistics_by_line_feat(lines, raster, statistic, new_field): """ Estimates raster statistic per line on a linear feature class statistic = statistic type (e.g. max, min, mean, sum) This method has an important problem - depends on the number of vertex of each features TODO: convert lines to raster and use the raster to get the statistics of each line """ from osgeo import ogr, gdal from gasp.gt.prop.ff import drv_name from gasp.gt.sample import pnt_val_on_rst # Open feature class shp = ogr.GetDriverByName(drv_name(lines)).Open(lines, 1) lyr = shp.GetLayer() # Create new field lyr.CreateField(ogr.FieldDefn(new_field, ogr.OFTReal)) # Open Raster img = gdal.Open(raster) geo_transform = img.GetGeoTransform() band = img.GetRasterBand(1) # For feature in layer for feat in lyr: rst_values = [] # For point in line lnh = feat.GetGeometryRef() num_pnt = lnh.GetPointCount() for pnt in range(num_pnt): x, y, z = lnh.GetPoint(pnt) cell = pnt_val_on_rst(x, y, band, geo_transform) if not cell: continue else: rst_values.append(cell) if len(rst_values): if statistic == 'minimum': value = min(rst_values) elif statistic == 'maximum': value = max(rst_values) elif statistic == 'mean': value = sum(rst_values) / len(rst_values) elif statistic == 'sum': value = sum(rst_values) else: continue feat.SetField(new_field, value) lyr.SetFeature(feat)
def get_attr_values_in_location(inShp, attr, geomFilter=None, shpFilter=None): """ Get attributes of the features of inShp that intersects with geomFilter or shpFilter """ from osgeo import ogr from gasp.gt.prop.ff import drv_name if not geomFilter and not shpFilter: raise ValueError( 'A geom object or a path to a sho file should be given') if shpFilter: # For now the shpFilter must have only one feature filter_shp = ogr.GetDriverByName(drv_name(shpFilter)).Open( shpFilter, 0) filter_lyr = filter_shp.GetLayer() c = 0 for f in filter_lyr: if c: break geom = f.GetGeometryRef() c += 1 filter_shp.Destroy() else: geom = geomFilter # Open Main data dtSrc = ogr.GetDriverByName(drv_name(inShp)).Open(inShp, 0) lyr = dtSrc.GetLayer() lyr.SetSpatialFilter(geom) # Get attribute values ATTRIBUTE_VAL = [feat.GetField(attr) for feat in lyr] dtSrc.Destroy() return ATTRIBUTE_VAL
def clip(inFeat, clipFeat, outFeat, api_gis="grass", clip_by_region=None): """ Clip Analysis api_gis Options: * grass * pygrass * ogr2ogr """ if api_gis == "pygrass": from grass.pygrass.modules import Module if not clip_by_region: vclip = Module("v.clip", input=inFeat, clip=clipFeat, output=outFeat, overwrite=True, run_=False, quiet=True) else: vclip = Module("v.clip", input=inFeat, output=outFeat, overwrite=True, flags='r', run_=False, quiet=True) vclip() elif api_gis == "grass": from gasp import exec_cmd rcmd = exec_cmd( "v.clip input={}{} output={} {}--overwrite --quiet".format( inFeat, " clip={}".format(clipFeat) if clipFeat else "", outFeat, "-r " if not clipFeat else "")) elif api_gis == 'ogr2ogr': from gasp import exec_cmd from gasp.pyt.oss import fprop from gasp.gt.prop.ff import drv_name rcmd = exec_cmd( ("ogr2ogr -f \"{}\" {} {} -clipsrc {} -clipsrclayer {}").format( drv_name(outFeat), outFeat, inFeat, clipFeat, fprop(clipFeat, 'fn'))) else: raise ValueError("{} is not available!".format(api_gis)) return outFeat
def gpkgrst_to_rst(gpkg, tbl, outrst): """ Convert Raster in GeoPackage to single file """ from gasp import exec_cmd from gasp.gt.prop.ff import drv_name rcmd = exec_cmd("gdal_translate -of {} {} {} -b 1 -oo TABLE={}".format( drv_name(outrst), gpkg, outrst, tbl)) return outrst
def rst_to_rst(inRst, outRst): """ Convert a raster file to another raster format """ from gasp import exec_cmd from gasp.gt.prop.ff import drv_name outDrv = drv_name(outRst) cmd = 'gdal_translate -of {drv} {_in} {_out}'.format(drv=outDrv, _in=inRst, _out=outRst) cmdout = exec_cmd(cmd) return outRst
def shpext_to_boundshp(inShp, outShp, epsg=None): """ Read one feature class extent and create a boundary with that extent The outFile could be a Feature Class or one Raster Dataset """ import os from osgeo import ogr from gasp.gt.prop.ff import drv_name from gasp.pyt.oss import fprop from gasp.g.to import new_pnt from gasp.g.to import shpext_to_boundary # Get SRS for the output if not epsg: from gasp.gt.prop.prj import get_shp_sref srs = get_shp_sref(inShp) else: from gasp.gt.prop.prj import get_sref_from_epsg srs= get_sref_from_epsg(epsg) # Write new file shp = ogr.GetDriverByName( drv_name(outShp)).CreateDataSource(outShp) lyr = shp.CreateLayer( fprop(outShp, 'fn', forceLower=True), srs, geom_type=ogr.wkbPolygon ) outDefn = lyr.GetLayerDefn() feat = ogr.Feature(outDefn) polygon = shpext_to_boundary(inShp) feat.SetGeometry(polygon) lyr.CreateFeature(feat) feat.Destroy() shp.Destroy() return outShp
def dic_buffer_array_to_shp(arrayBf, outShp, epsg, fields=None): """ Array with dict with buffer proprieties to Feature Class """ import os from osgeo import ogr from gasp.gt.prop.ff import drv_name from gasp.gt.prop.prj import get_sref_from_epsg # Get SRS for output srs = get_sref_from_epsg(epsg) # Create output DataSource and Layer outData = ogr.GetDriverByName(drv_name(outShp)).CreateDataSource(outShp) lyr = outData.CreateLayer(os.path.splitext(os.path.basename(outShp))[0], srs, geom_type=ogr.wkbPolygon) # Create fields if fields: from gasp.g.lyr.fld import fields_to_lyr fields_to_lyr(lyr, fields) lyrDefn = lyr.GetLayerDefn() for _buffer in arrayBf: newFeat = ogr.Feature(lyrDefn) geom = coord_to_buffer(_buffer["X"], _buffer["Y"], _buffer["RADIUS"]) newFeat.SetGeometry(geom) for field in fields: if field in _buffer.keys(): newFeat.SetField(field, _buffer[field]) lyr.CreateFeature(newFeat) newFeat.Destroy() del lyrDefn outData.Destroy() return outShp
def feat_count(shp, gisApi='pandas', work=None, loc=None): """ Count the number of features in a feature class API'S Available: * gdal; * arcpy; * pygrass; * pandas; """ if gisApi == 'ogr': from osgeo import ogr from gasp.gt.prop.ff import drv_name data = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = data.GetLayer() fcnt = int(lyr.GetFeatureCount()) data.Destroy() elif gisApi == 'grass': if not work or not loc: raise ValueError( ("If gisApi=='grass', work and loc must be defined!")) import os from gasp.sql.i import row_num db = os.path.join(work, loc, 'PERMANENT', 'sqlite', 'sqlite.db') fcnt = row_num(db, shp, api='sqlite') elif gisApi == 'pandas': from gasp.gt.fmshp import shp_to_obj gdf = shp_to_obj(shp) fcnt = int(gdf.shape[0]) del gdf else: raise ValueError('The api {} is not available'.format(gisApi)) return fcnt
def clip_rst(raster, clipShp, outRst, nodataValue=None, api='gdal'): """ Clip Raster using GDAL WARP """ if api == 'gdal': from gasp import exec_cmd from gasp.gt.prop.ff import drv_name outcmd = exec_cmd( ("gdalwarp {ndata}-cutline {clipshp} -crop_to_cutline " "-of {ext} {inraster} -overwrite {outrst}").format( clipshp=clipShp, inraster=raster, outrst=outRst, ext=drv_name(outRst), ndata="-dstnodata {} ".format(str(nodataValue)) if nodataValue else "")) elif api == 'pygrass': from grass.pygrass.modules import Module m = Module('r.clip', input=raster, output=outRst, overwrite=True, run_=False, quiet=True) m() elif api == 'grass': from gasp import exec_cmd rcmd = exec_cmd('r.clip input={} output={} --overwrite --quiet'.format( raster, outRst)) else: raise ValueError('API {} is not available'.format(api)) return outRst
def rst_val_to_points2(pntShp, listRasters): """ Pick raster value for each point in pntShp """ from osgeo import ogr from gasp.pyt import obj_to_lst from gasp.gt.prop.ff import drv_name listRasters = obj_to_lst(listRasters) shp = ogr.GetDriverByName(drv_name(pntShp)).Open(pnt, 0) lyr = shp.GetLayer() pntDict = {} for feat in lyr: geom = feat.GetGeometryRef() x, y = geom.GetX(), geom.GetY() l = [] for rst in listRasters: img = gdal.Open(rst) geo_transform = img.GetGeoTransform() band = img.GetRasterBand(1) px = int((x - geo_transform[0]) / geo_transform[1]) py = int((y - geo_transform[3]) / geo_transform[5]) value = band.ReadAsArray(px, py, 1, 1) l.append(list(value)[0]) del img, geo_transform, band, px, py pntDict[feat.GetFID()] = l shp.Destroy() return pntDict
def comp_bnds(rsts, outRst): """ Composite Bands """ from osgeo import gdal, gdal_array from gasp.gt.fmrst import rst_to_array from gasp.gt.prop.ff import drv_name from gasp.gt.prop.rst import get_nodata from gasp.gt.prop.prj import get_rst_epsg, epsg_to_wkt # Get Arrays _as = [rst_to_array(r) for r in rsts] # Get nodata values nds = [get_nodata(r) for r in rsts] # Assume that first raster is the template img_temp = gdal.Open(rsts[0]) geo_tran = img_temp.GetGeoTransform() band = img_temp.GetRasterBand(1) dataType = gdal_array.NumericTypeCodeToGDALTypeCode(_as[0].dtype) rows, cols = _as[0].shape epsg = get_rst_epsg(rsts[0]) # Create Output drv = gdal.GetDriverByName(drv_name(outRst)) out = drv.Create(outRst, cols, rows, len(_as), dataType) out.SetGeoTransform(geo_tran) out.SetProjection(epsg_to_wkt(epsg)) # Write all bands for i in range(len(_as)): outBand = out.GetRasterBand(i + 1) outBand.SetNoDataValue(nds[i]) outBand.WriteArray(_as[i]) outBand.FlushCache() return outRst
def shp_to_shp(inShp, outShp, gisApi='ogr', supportForSpatialLite=None): """ Convert a vectorial file to another with other file format API's Available: * ogr; When using gisApi='ogr' - Set supportForSpatialLite to True if outShp is a sqlite db and if you want SpatialLite support for that database. """ import os if gisApi == 'ogr': from gasp import exec_cmd from gasp.gt.prop.ff import drv_name out_driver = drv_name(outShp) if out_driver == 'SQLite' and supportForSpatialLite: splite = ' -dsco "SPATIALITE=YES"' else: splite = '' cmd = 'ogr2ogr -f "{drv}" {out} {_in}{lite}'.format( drv=out_driver, out=outShp, _in=inShp, lite=splite ) # Run command cmdout = exec_cmd(cmd) else: raise ValueError('Sorry, API {} is not available'.format(gisApi)) return outShp
def get_ext(shp): """ Return extent of a Vectorial file Return a tuple object with the follow order: (left, right, bottom, top) API'S Available: * ogr; """ gisApi = 'ogr' if gisApi == 'ogr': from osgeo import ogr from gasp.gt.prop.ff import drv_name dt = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = dt.GetLayer() extent = lyr.GetExtent() dt.Destroy() return list(extent)
def coords_to_boundshp(topLeft, lowerRight, epsg, outshp, outEpsg=None): """ Top Left and Lower Right to Boundary """ import os; from osgeo import ogr from gasp.gt.prop.ff import drv_name from gasp.gt.prop.prj import get_sref_from_epsg from gasp.pyt.oss import fprop from gasp.g.to import coords_to_boundary # Get boundary geometry polygon = coords_to_boundary(topLeft, lowerRight, epsg, outEpsg=outEpsg) # Create outShapefile if a path is given shp = ogr.GetDriverByName( drv_name(outshp)).CreateDataSource(outshp) SRS_OBJ = get_sref_from_epsg(epsg) if not outEpsg else \ get_sref_from_epsg(outEpsg) lyr = shp.CreateLayer(fprop( outshp, 'fn'), SRS_OBJ, geom_type=ogr.wkbPolygon ) outDefn = lyr.GetLayerDefn() feat = ogr.Feature(outDefn) feat.SetGeometry(polygon) lyr.CreateFeature(feat) feat.Destroy() shp.Destroy() return outshp
def ogr_buffer(geom, radius, out_file, srs=None): """ For each geometry in the input, this method create a buffer and store it in a vetorial file Accepts files or lists with geom objects as inputs """ import os from osgeo import ogr from gasp.gt.prj import def_prj from gasp.gt.prop.ff import drv_name from gasp.gt.prop.prj import get_sref_from_epsg from gasp.g.gop.prox import draw_buffer # Create output buffer_shp = ogr.GetDriverByName( drv_name(out_file)).CreateDataSource(out_file) buffer_lyr = buffer_shp.CreateLayer( os.path.splitext(os.path.basename(out_file))[0], get_sref_from_epsg(srs) if srs else None, geom_type=ogr.wkbPolygon) featDefn = buffer_lyr.GetLayerDefn() if type(geom) == list: for g in geom: feat = ogr.Feature(featDefn) feat.SetGeometry(draw_buffer(g, radius)) buffer_lyr.CreateFeature(feat) feat = None buffer_shp.Destroy() elif type(geom) == dict: if 'x' in geom and 'y' in geom: X = 'x' Y = 'y' elif 'X' in geom and 'Y' in geom: X = 'X' Y = 'Y' else: raise ValueError(('Your geom dict has invalid keys. ' 'Please use one of the following combinations: ' 'x, y; ' 'X, Y')) from gasp.g.to import new_pnt feat = ogr.Feature(featDefn) g = new_pnt(geom[X], geom[Y]) feat.SetGeometry(draw_buffer(g, radius)) buffer_lyr.CreateFeature(feat) feat = None buffer_shp.Destroy() if srs: def_prj(out_file, epsg=srs) elif type(geom) == str: # Check if the input is a file if os.path.exists(geom): inShp = ogr.GetDriverByName(drv_name(geom)).Open(geom, 0) lyr = inShp.GetLayer() for f in lyr: g = f.GetGeometryRef() feat = ogr.Feature(featDefn) feat.SetGeometry(draw_buffer(g, radius)) buffer_lyr.CreateFeature(feat) feat = None buffer_shp.Destroy() inShp.Destroy() if srs: def_prj(out_file, epsg=srs) else: def_prj(out_file, template=geom) else: raise ValueError('The given path does not exist') else: raise ValueError('Your geom input is not valid') return out_file
def rsts_to_mosaic(inRasterS, o, api="grass", fformat='.tif'): """ Create Mosaic of Raster """ if api == 'pygrass': """ The GRASS program r.patch allows the user to build a new raster map the size and resolution of the current region by assigning known data values from input raster maps to the cells in this region. This is done by filling in "no data" cells, those that do not yet contain data, contain NULL data, or, optionally contain 0 data, with the data from the first input map. Once this is done the remaining holes are filled in by the next input map, and so on. This program is useful for making a composite raster map layer from two or more adjacent map layers, for filling in "holes" in a raster map layer's data (e.g., in digital elevation data), or for updating an older map layer with more recent data. The current geographic region definition and mask settings are respected. The first name listed in the string input=name,name,name, ... is the name of the first map whose data values will be used to fill in "no data" cells in the current region. The second through last input name maps will be used, in order, to supply data values for for the remaining "no data" cells. """ from grass.pygrass.modules import Module m = Module( "r.patch", input=inRasterS, output=o, overwrite=True, run_=False, quiet=True ) m() elif api == 'grass': from gasp import exec_cmd rcmd = exec_cmd("r.patch input={} output={} --overwrite --quiet".format( ",".join(inRasterS), o )) elif api == 'rasterio': import os; import rasterio from rasterio.merge import merge from gasp.gt.prop.ff import drv_name if type(inRasterS) != list: from gasp.pyt.oss import lst_ff rsts = lst_ff(inRasterS, file_format=fformat) else: rsts = inRasterS srcs = [rasterio.open(r) for r in rsts] mosaic, out_trans = merge(srcs) out_meta = srcs[0].meta.copy() out_meta.update({ "driver" : drv_name(o), "height" : mosaic.shape[1], "width" : mosaic.shape[2], "transform" : out_trans, "compress" : 'lzw' }) with rasterio.open(o, "w", **out_meta) as dest: dest.write(mosaic) else: raise ValueError('api {} is not available'.format(api)) return o
def proj(inShp, outShp, outEPSG, inEPSG=None, gisApi='ogr', sql=None, db_name=None): """ Project Geodata using GIS API's Available: * ogr; * ogr2ogr; * pandas; * ogr2ogr_SQLITE; * psql; """ import os if gisApi == 'ogr': """ Using ogr Python API """ if not inEPSG: raise ValueError( 'To use ogr API, you should specify the EPSG Code of the' ' input data using inEPSG parameter' ) from osgeo import ogr from gasp.g.lyr.fld import copy_flds from gasp.gt.prop.feat import get_gtype from gasp.gt.prop.ff import drv_name from gasp.gt.prop.prj import get_sref_from_epsg, get_trans_param from gasp.pyt.oss import fprop def copyShp(out, outDefn, lyr_in, trans): for f in lyr_in: g = f.GetGeometryRef() g.Transform(trans) new = ogr.Feature(outDefn) new.SetGeometry(g) for i in range(0, outDefn.GetFieldCount()): new.SetField(outDefn.GetFieldDefn(i).GetNameRef(), f.GetField(i)) out.CreateFeature(new) new.Destroy() f.Destroy() # ####### # # Project # # ####### # transP = get_trans_param(inEPSG, outEPSG) inData = ogr.GetDriverByName( drv_name(inShp)).Open(inShp, 0) inLyr = inData.GetLayer() out = ogr.GetDriverByName( drv_name(outShp)).CreateDataSource(outShp) outlyr = out.CreateLayer( fprop(outShp, 'fn'), get_sref_from_epsg(outEPSG), geom_type=get_gtype( inShp, name=None, py_cls=True, gisApi='ogr' ) ) # Copy fields to the output copy_flds(inLyr, outlyr) # Copy/transform features from the input to the output outlyrDefn = outlyr.GetLayerDefn() copyShp(outlyr, outlyrDefn, inLyr, transP) inData.Destroy() out.Destroy() elif gisApi == 'ogr2ogr': """ Transform SRS of any OGR Compilant Data. Save the transformed data in a new file """ if not inEPSG: from gasp.gt.prop.prj import get_epsg_shp inEPSG = get_epsg_shp(inShp) if not inEPSG: raise ValueError('To use ogr2ogr, you must specify inEPSG') from gasp import exec_cmd from gasp.gt.prop.ff import drv_name cmd = ( 'ogr2ogr -f "{}" {} {}{} -s_srs EPSG:{} -t_srs EPSG:{}' ).format( drv_name(outShp), outShp, inShp, '' if not sql else ' -dialect sqlite -sql "{}"'.format(sql), str(inEPSG), str(outEPSG) ) outcmd = exec_cmd(cmd) elif gisApi == 'ogr2ogr_SQLITE': """ Transform SRS of a SQLITE DB table. Save the transformed data in a new table """ from gasp import exec_cmd if not inEPSG: raise ValueError(( 'With ogr2ogr_SQLITE, the definition of inEPSG is ' 'demandatory.' )) # TODO: Verify if database is sqlite db, tbl = inShp['DB'], inShp['TABLE'] sql = 'SELECT * FROM {}'.format(tbl) if not sql else sql outcmd = exec_cmd(( 'ogr2ogr -update -append -f "SQLite" {db} -nln "{nt}" ' '-dialect sqlite -sql "{_sql}" -s_srs EPSG:{inepsg} ' '-t_srs EPSG:{outepsg} {db}' ).format( db=db, nt=outShp, _sql=sql, inepsg=str(inEPSG), outepsg=str(outEPSG) )) elif gisApi == 'pandas': # Test if input Shp is GeoDataframe from gasp.gt.fmshp import shp_to_obj from gasp.gt.toshp import df_to_shp df = shp_to_obj(inShp) # Project df newDf = df.to_crs({'init' : 'epsg:{}'.format(str(outEPSG))}) # Save as file return df_to_shp(df, outShp) elif gisApi == 'psql': from gasp.sql.db import create_db from gasp.pyt.oss import fprop from gasp.gql.to import shp_to_psql from gasp.gt.toshp.db import dbtbl_to_shp from gasp.gql.prj import sql_proj # Create Database if not db_name: db_name = create_db(fprop( outShp, 'fn', forceLower=True), api='psql' ) else: from gasp.sql.i import db_exists isDb = db_exists(db_name) if not isDb: create_db(db_name, api='psql') # Import Data inTbl = shp_to_psql(db_name, inShp, api='shp2pgsql', encoding="LATIN1") # Transform oTbl = sql_proj( db_name, inTbl, fprop(outShp, 'fn', forceLower=True), outEPSG, geomCol='geom', newGeom='geom' ) # Export outShp = dbtbl_to_shp( db_name, oTbl, 'geom', outShp, api='psql', epsg=outEPSG ) else: raise ValueError('Sorry, API {} is not available'.format(gisApi)) return outShp
def rst_to_polyg(inRst, outShp, rstColumn=None, gisApi='gdal', epsg=None): """ Raster to Polygon Shapefile Api's Available: * gdal; * qgis; * pygrass; * grass; """ if gisApi == 'gdal': if not epsg: raise ValueError( ('Using GDAL, you must specify the EPSG CODE of the ' 'Spatial Reference System of input raster.')) import os from osgeo import gdal, ogr, osr from gasp.gt.prop.ff import drv_name from gasp.pyt.oss import fprop src = gdal.Open(inRst) bnd = src.GetRasterBand(1) output = ogr.GetDriverByName(drv_name(ouShp)).CreateDataSource(outShp) srs = osr.SpatialReference() srs.ImportFromEPSG(epsg) lyr = output.CreateLayer(fprop(outShp, 'fn', forceLower=True), srs) lyr.CreateField(ogr.FieldDefn('VALUE', ogr.OFTInteger)) gdal.Polygonize(bnd, None, lyr, 0, [], callback=None) output.Destroy() elif gisApi == 'qgis': import processing processing.runalg("gdalogr:polygonize", inRst, "value", outShp) elif gisApi == 'pygrass': from grass.pygrass.modules import Module rstField = "value" if not rstColumn else rstColumn rtop = Module("r.to.vect", input=inRst, output=outShp, type="area", column=rstField, overwrite=True, run_=False, quiet=True) rtop() elif gisApi == 'grass': from gasp import exec_cmd rstField = "value" if not rstColumn else rstColumn rcmd = exec_cmd(("r.to.vect input={} output={} type=area column={} " "--overwrite --quiet").format(inRst, outShp, rstField)) else: raise ValueError('Sorry, API {} is not available'.format(gisApi)) return outShp
def shps_to_shp(shps, outShp, api="ogr2ogr", fformat='.shp', dbname=None): """ Get all features in several Shapefiles and save them in one file api options: * ogr2ogr; * psql; * pandas; * psql; """ import os if type(shps) != list: # Check if is dir if os.path.isdir(shps): from gasp.pyt.oss import lst_ff # List shps in dir shps = lst_ff(shps, file_format=fformat) else: raise ValueError(( 'shps should be a list with paths for Feature Classes or a path to ' 'folder with Feature Classes')) if api == "ogr2ogr": from gasp import exec_cmd from gasp.gt.prop.ff import drv_name out_drv = drv_name(outShp) # Create output and copy some features of one layer (first in shps) cmdout = exec_cmd('ogr2ogr -f "{}" {} {}'.format( out_drv, outShp, shps[0])) # Append remaining layers lcmd = [ exec_cmd('ogr2ogr -f "{}" -update -append {} {}'.format( out_drv, outShp, shps[i])) for i in range(1, len(shps)) ] elif api == 'pandas': """ Merge SHP using pandas """ from gasp.gt.fmshp import shp_to_obj from gasp.gt.toshp import df_to_shp if type(shps) != list: raise ValueError( 'shps should be a list with paths for Feature Classes') dfs = [shp_to_obj(shp) for shp in shps] result = dfs[0] for df in dfs[1:]: result = result.append(df, ignore_index=True, sort=True) df_to_shp(result, outShp) elif api == 'psql': import os from gasp.sql.tbl import tbls_to_tbl, del_tables from gasp.gql.to import shp_to_psql if not dbname: from gasp.sql.db import create_db create_db(dbname, api='psql') pg_tbls = shp_to_psql(dbname, shps, api="shp2pgsql") if os.path.isfile(outShp): from gasp.pyt.oss import fprop outbl = fprop(outShp, 'fn') else: outbl = outShp tbls_to_tbl(dbname, pg_tbls, outbl) if outbl != outShp: from gasp.gt.toshp.db import dbtbl_to_shp dbtbl_to_shp(dbname, outbl, 'geom', outShp, inDB='psql', api="pgsql2shp") del_tables(dbname, pg_tbls) elif api == 'grass': from gasp import exec_cmd rcmd = exec_cmd( ("v.patch input={} output={} --overwrite --quiet").format( ",".join(shps), outShp)) else: raise ValueError("{} API is not available") return outShp