def transform_geojson_wgs_to_epsg(geojson, EPSG): """ Takes a geojson dictionary and converts it from WGS84 (EPSG:4326) to desired EPSG Parameters ---------- geojson: dict a geojson dictionary containing a 'geometry' key, in WGS84 coordinates EPSG: int numeric code for the EPSG coordinate referecnce system to transform into Returns ------- transformed_geojson: dict a geojson dictionary containing a 'coordinates' key, in the desired CRS """ geojson_geom = geojson['geometry'] polygon = ogr.CreateGeometryFromJson(str(geojson_geom)) source = osr.SpatialReference() source.ImportFromEPSG(4326) target = osr.SpatialReference() target.ImportFromEPSG(EPSG) transform = osr.CoordinateTransformation(source, target) polygon.Transform(transform) transformed_geojson = eval(polygon.ExportToJson()) return transformed_geojson
def Create_Geometry_from_GeoJSON(geojson): from osgeo import ogr geojson = """{"type":"Point","coordinates":[108420.33,753808.59]}""" point = ogr.CreateGeometryFromJson(geojson) print("%d,%d" % (point.GetX(), point.GetY())) return point
def create_feature(self, layer, featureDict, expected_type, srs=None): try: geom_dict = featureDict["geometry"] if not geom_dict: raise EsriFeatureLayerException("No Geometry Information") geom_type = geom_dict["type"] feature = ogr.Feature(layer.GetLayerDefn()) coords = self.get_geom_coords(geom_dict) f_json = json.dumps({"type": geom_type, "coordinates": coords}) geom = ogr.CreateGeometryFromJson(f_json) if geom and srs: geom.Transform(srs) if geom and expected_type != geom.GetGeometryType(): geom = ogr.ForceTo(geom, expected_type) if geom and expected_type == geom.GetGeometryType( ) and geom.IsValid(): feature.SetGeometry(geom) for prop, val in featureDict["properties"].items(): name = str(SLUGIFIER(prop)).encode('utf-8') value = val if value and layer.GetLayerDefn().GetFieldIndex( name) != -1: feature.SetField(name, value) layer.CreateFeature(feature) except Exception as e: logger.error(e)
def concatenateControlPoints(projects, outputFolder): spatialRef = None cpList = [] for proj in projects: controlPointsPath = proj['project'].getpath('Control_Points') vid = proj['visit'] cpShp = Shapefile(controlPointsPath) visitCPList = cpShp.featuresToShapely() spatialRef = cpShp.spatialRef for aPoint in visitCPList: cpItems = {} cpItems['geometry'] = aPoint['geometry'] cpItems['fields'] = {} cpItems['fields']['VisitID'] = int(vid) cpItems['fields']['PointNum'] = getFieldValue( aPoint['fields'], [ 'Point_Numb', 'POINT_NUMB', 'PointNumb', 'POINT_NUM', 'POINT' ]) cpItems['fields']['Code'] = getFieldValue( aPoint['fields'], ['DESCRIPTIO', 'Descriptio', 'Code']) cpItems['fields']['Type'] = getFieldValue(aPoint['fields'], ['Type', 'TYPE']) cpList.append(cpItems) outputPath = os.path.join(outputFolder, "AllVisitControlPoints.shp") print "Writing combined control points to {0}".format(outputPath) outShape = Shapefile() outShape.create(outputPath, spatialRef, geoType=ogr.wkbPointZM) outShape.createField("ID", ogr.OFTInteger) outShape.createField("VisitID", ogr.OFTInteger) outShape.createField("PointNum", ogr.OFTString) outShape.createField("Code", ogr.OFTString) outShape.createField("Type", ogr.OFTString) id = 1 for aCP in cpList: featureDefn = outShape.layer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) ogrPolygon = ogr.CreateGeometryFromJson( json.dumps(mapping(aCP['geometry']))) outFeature.SetGeometry(ogrPolygon) outFeature.SetField('ID', id) id += 1 for fieldName, fieldValue in aCP['fields'].iteritems(): outFeature.SetField(fieldName, fieldValue) outShape.layer.CreateFeature(outFeature)
def _create_base_map(self, ): ''' Deal with different types way to define the AOI, if none is specified, then the image bound is used. ''' if self.aoi is not None: if os.path.exists(self.aoi): try: g = gdal.Open(self.aoi) subprocess.call([ 'gdaltindex', '-f', 'GeoJSON', self.toa_dir + '/AOI.json', self.aoi ]) except: try: g = ogr.Open(self.aoi) except: raise IOError( 'AOI file cannot be opened by gdal, please check it or transform into format can be opened by gdal' ) else: try: g = ogr.CreateGeometryFromJson(aoi) except: try: g = ogr.CreateGeometryFromGML(aoi) except: try: g = ogr.CreateGeometryFromWkt(aoi) except: try: g = ogr.CreateGeometryFromWkb(aoi) except: raise IOError( 'The AOI has to be one of GeoJSON, GML, Wkt or Wkb.' ) gjson_str = '''{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":%s}]}''' % g.ExportToJson( ) with open(self.toa_dir + '/AOI.json', 'wb') as f: f.write(gjson_str) if not os.path.exists(self.toa_dir + '/AOI.json'): subprocess.call([ 'gdaltindex', '-f', 'GeoJSON', self.toa_dir + '/AOI.json', self.toa_bands[0] ]) self.logger.warning( 'AOI is not created and full band extend is used') self.aoi = self.toa_dir + '/AOI.json' else: self.aoi = self.toa_dir + '/AOI.json' if self.pixel_res is None: self.pixel_res = abs( gdal.Open(self.toa_bands[0]).GetGeoTransform()[1]) self.psf_xstd = 260 / self.pixel_res self.psf_ystd = 340 / self.pixel_res
def gml2json(self, gml): json_out = { "type": "FeatureCollection", "features": [], } geom_crs = None tree = etree.fromstring(gml) nsmap = tree.nsmap tag_name = lambda t: t.tag.split("{%s}" % nsmap[t.prefix])[-1] for feature in tree.getiterator("{%s}featureMember" % nsmap["gml"]): json_feature = { "type": "Feature", "properties": {}, "geometry": None, } for layer in feature.iterfind('{%s}*' % nsmap["ms"]): json_feature["properties"]["layer"] = tag_name(layer) wfs_id = layer.get("{%s}id" % nsmap["gml"], None) if wfs_id and self.map_name_use: wfs_id = u"{0}.{1}".format(self.map_name_use, wfs_id) json_feature["properties"]["id"] = wfs_id for prop in layer.iterfind('{%s}*' % nsmap["ms"]): get_prop = True for geom in prop.iterfind("{%s}*" % nsmap["gml"]): get_prop = False geom_crs = geom.get("srsName", None) ogr_geom = ogr.CreateGeometryFromGML( etree.tostring(geom)) if isinstance(ogr_geom, ogr.Geometry): json_feature["geometry"] = json.loads( ogr_geom.ExportToJson()) if geom_crs: json_feature["geometry"][ "crs"] = self.create_json_crs(geom_crs) if self.out_geom: ogr_geom = ogr.CreateGeometryFromJson( str( json.dumps(json_feature["geometry"], ensure_ascii=False))) if self.out_geom == "gml": json_feature[ "geometry"] = ogr_geom.ExportToGML() elif self.out_geom == "wkt": json_feature[ "geometry"] = ogr_geom.ExportToWkt() else: raise Exception( 'out_geom="{} is not valid (None,gml,wkt)use"' .format(self.out_geom)) if get_prop: json_feature["properties"][tag_name(prop)] = prop.text json_out["features"].append(json_feature) if geom_crs: json_out["crs"] = self.create_json_crs(geom_crs) if self.debug: self.echo2json(json_out) return json_out
def queryRegion(data): # Get data from web app d = {'property':'default', 'reducer':'default', 'format':'json'} d.update(data) dataset = d['dataset'].strip() property = d['property'].strip() reducer = d['reducer'] region = d['region'] format = d['format'] dates = json.loads(d['date']) # Input normalization if isinstance(dates, basestring): dates = [dates] dates = [parseDate(x) for x in dates] if isinstance(reducer, basestring): reducer = [x.strip() for x in reducer.split(',')] # Read Metadata metadata = readMetadata(dataset) # Update defaults from metadata if d['property'] == 'default': d['property'] = metadata['default-property'] if d['reducer'] == 'default': d['reducer'] == metadata['default-reducer'] # Presume a geojson srs of EPSG:4326 geom = ogr.CreateGeometryFromJson(region.encode('utf-8')) srs = osr.SpatialReference() srs.ImportFromEPSG(4326) geom.AssignSpatialReference(srs) # Get raster path rasterfn = getDatasetPath(dataset) + '/{property}.vrt'.format(property=property) # Determine required bands bandDates = metadata['band-dates'] bands = selectBandsByDate(dates, bandDates) values = fetchRegion(geom, rasterfn, bands) response = {'dataset':dataset, 'property':property, } out = {str(bandDates[x]):values[x] for x in values} for r in reducer: response[r] = reduce(out, r) if format == 'yaml': return yaml.dump(response) else: return json.dumps(response)
def shapelyToFeatures(self, shplyFeat, outShp, spatialRef, geoType): self.create(outShp, spatialRef, geoType) featureDefn = self.layer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) ogrJsonDump = ogr.CreateGeometryFromJson(json.dumps( mapping(shplyFeat))) outFeature.SetGeometry(ogrJsonDump) self.layer.CreateFeature(outFeature) return outFeature
def transform_geom(self, geometry): if geometry.find('{') >= 0 : geom = ogr.CreateGeometryFromJson(geometry) else: geom = ogr.CreateGeometryFromWkt(geometry) if self.transform is not None: geom.Transform(self.transform) return geom
def createPoint(point_json, shp_name, field): ''' 生成点shp文件 输入: point_json:描述点的geojson文件 name:要生成的shp文件名 field:shp文件中的字段名及数据类型 {字段1:类型1,字段2:类型2,字段3:类型3} 常见数据类型:ogr.OFTString ogr.OFTReal ogr.OFTInteger ''' # 设置shapefile驱动 gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES") gdal.SetConfigOption("SHAPE_ENCODING", "gbk") driver = ogr.GetDriverByName("ESRI Shapefile") # 创建数据源 data_source = driver.CreateDataSource(shp_name) # 创建空间参考,WGS84 srs = osr.SpatialReference() srs.ImportFromEPSG(4326) # 创建图层 layer = data_source.CreateLayer("point", srs, ogr.wkbPoint) # 带坐标系文件 # 设置字段 for field_name, field_type in field.items(): if len(field_name) > 10: fn = ogr.FieldDefn(field_name[0:10], field_type) else: fn = ogr.FieldDefn(field_name, field_type) #数据类型为str时,设置字段长度 if field_type == ogr.OFTString: fn.SetWidth(128) layer.CreateField(fn) for point in point_json['features']: # 创建特征 feature = ogr.Feature(layer.GetLayerDefn()) # 和设置字段内容进行关联 ,从数据源中写入数据 for field_name, _ in field.items(): if len(field_name) > 10: feature.SetField(field_name[0:10], point['properties'][field_name]) else: feature.SetField(field_name, point['properties'][field_name]) # 生成点坐标 point_geo = ogr.CreateGeometryFromJson(str(point['geometry'])) feature.SetGeometry(point_geo) # 添加点 layer.CreateFeature(feature) # 关闭 特征 feature = None # 关闭数据 data_source = None
def filter_spat_buffer(self, propertyname=None, coord=None, radius=None, epsg_code=None, epsg_code_measure=3857): if isinstance(coord, (list, tuple)) and isinstance(radius, (int, float)): # lat <-> lon coord = [ coord[-1], coord[0] ] in_srs = osr.SpatialReference() in_srs.ImportFromEPSG(int(epsg_code["crs"]["properties"]["code"])) out_srs = osr.SpatialReference() out_srs.ImportFromEPSG(int(epsg_code_measure)) # detect type coordinate system if out_srs.ExportToPCI()[1] != "METRE": raise Exception("'epsg_code_measure' is not geometric coordinate system") json_geom = { "type": "Point", "coordinates": coord } json_geom.update(epsg_code) # transform to measure epsg code transform = osr.CoordinateTransformation(in_srs, out_srs) ogr_geom = ogr.CreateGeometryFromJson( json.dumps( json_geom, ensure_ascii=False ) ) ogr_geom.Transform(transform) # create buffer gml_geom = ogr_geom.Buffer(radius*2).ExportToGML() prop_name = u"<ogc:PropertyName>{}</ogc:PropertyName>".format( self.geom_property_cap ) return u"<ogc:Intersects>{0}{1}</ogc:Intersects>".format( prop_name, gml_geom ) elif not propertyname and not coord and not radius: return { "coord": [ "Latitude point", "Longitude point", ], "radius": "radius in meters", "epsg_code_measure": "epsg code for radius measuring, default 3857", "epsg_code": "epsg code projection", } else: raise Exception("Filter buffer: error")
def overlapping_polygon_area(polys): """ Parameters ---------- polys : list of polygon object with a __geo_interface__ Returns ------- area : float The area of the intersecting polygons """ geom = json.dumps(polys[0].__geo_interface__) intersection = ogr.CreateGeometryFromJson(geom) for p in polys[1:]: geom = json.dumps(p.__geo_interface__) geom = ogr.CreateGeometryFromJson(geom) intersection = intersection.Intersection(geom) area = intersection.GetArea() return area
def convertGeometry(geom, srs): import ogr import osr in_ref = osr.SpatialReference() in_ref.SetFromUserInput(srs) out_ref = osr.SpatialReference() out_ref.SetFromUserInput('EPSG:4326') g = ogr.CreateGeometryFromJson(json.dumps(geom)) g.AssignSpatialReference(in_ref) g.TransformTo(out_ref) return json.loads(g.ExportToJson())
def transform_from_wgs_poly(geo_json, EPSGa): polygon = ogr.CreateGeometryFromJson(str(geo_json)) source = osr.SpatialReference() source.ImportFromEPSG(4326) target = osr.SpatialReference() target.ImportFromEPSG(EPSGa) transform = osr.CoordinateTransformation(source, target) polygon.Transform(transform) return eval(polygon.ExportToJson())
def writeShapeToShapeFile(outputPath, aPolygon, spatialRef): # Write the polygon to ShapeFile (note: ShapeFile handles deleting existing file) outShape = Shapefile() outShape.create(outputPath, spatialRef, geoType=ogr.wkbPolygon) outShape.createField("ID", ogr.OFTInteger) # The main centerline gets written first featureDefn = outShape.layer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) ogrPolygon = ogr.CreateGeometryFromJson(json.dumps(mapping(aPolygon))) outFeature.SetGeometry(ogrPolygon) outFeature.SetField('ID', 1) outShape.layer.CreateFeature(outFeature)
def handle(self, **options): import time #start_time = time.time() #self.method_one(options) #print("--- %s seconds ---" % (time.time() - start_time)) #start_time = time.time() #self.method_two(options) #print("--- %s seconds ---" % (time.time() - start_time)) #print 'Dataset was written.' output = options['output'][0] path = options['path'][0] #self.method_by_block(path, output) # set up the shapefile driver driver = ogr.GetDriverByName(str("ESRI Shapefile")) # create the data source data_source = driver.CreateDataSource(str(output)) # create the spatial reference, WGS84 srs = osr.SpatialReference() srs.ImportFromEPSG(4326) # create the layer layer = data_source.CreateLayer(str("volcanoes"), srs, geom_type=ogr.wkbPolygon) layer.CreateField(ogr.FieldDefn(str("code"), ogr.OFTInteger)) geom_type = ogr.wkbPolygon for state in get_rapideye_footprints_from_state('Chiapas'): feature = ogr.Feature(layer.GetLayerDefn()) feature.SetField(str("code"), int(state[0])) b = bytes(state[1]) print state[1] point = ogr.CreateGeometryFromJson(str(state[1])) # Set the feature geometry using the point feature.SetGeometry(point) layer.CreateFeature(feature) # Dereference the feature feature = None print state print output data_source = None
def geoJSONToShp(inJSON): # assumes WGS 84 # read poly from json poly = ogr.CreateGeometryFromJson(inJSON) # create a new shapefile to insert the new geometry into # https://pcjericks.github.io/py-gdalogr-cookbook/vector_layers.html#create-a-new-shapefile-and-add-data driver = ogr.GetDriverByName('ESRI Shapefile') tmp_dir = config.path_website + '/project/html/sites/all/modules/lsf_subscription/cgi-bin/shp_tmp/' #'/var/vsites/www.landsatfact.com/project/html/sites/all/modules/lsf_subscription/cgi-bin/shp_tmp/' # tmp_dir=r'H:\SPA_Secure\Geospatial\LandsatFACT\code\reduce\shapes' outShp = os.path.join(tmp_dir, 'tmp.shp') if os.path.exists(outShp): driver.DeleteDataSource(outShp) # Create the output shapefile target_srs = osr.SpatialReference() target_srs.ImportFromEPSG(4326) dataSource = driver.CreateDataSource(outShp) outLayer = dataSource.CreateLayer("tmp", target_srs, geom_type=ogr.wkbMultiPolygon) # Add an ID field idField = ogr.FieldDefn("id", ogr.OFTInteger) outLayer.CreateField(idField) # Create the feature and set values featureDefn = outLayer.GetLayerDefn() feature = ogr.Feature(featureDefn) feature.SetGeometry(poly) feature.SetField("id", 0) outLayer.CreateFeature(feature) # create an ESRI.prj file, https://pcjericks.github.io/py-gdalogr-cookbook/projection.html target_srs.MorphToESRI() prj = os.path.join( os.path.split(outShp)[0], os.path.splitext(os.path.basename(outShp))[0] + '.prj') file = open(prj, 'w') file.write(target_srs.ExportToWkt()) # Close and clean up neeeded to make sure shp is written file.close() dataSource.Destroy() # be careful with the order of clean (e.g., can't destroy feature until poly is dereferenced) geom = poly = driver = dataSource = target_srs = outLayer = file = feature = featureDefn = None return (countVertices(outShp))
def get_random_point(shp): with fiona.open(shp) as src: geom = src[0]['geometry'] geom = json.dumps(geom) polygon = ogr.CreateGeometryFromJson(geom) # print(polygon) env = polygon.GetEnvelope() xmin, ymin, xmax, ymax = env[0], env[2], env[1], env[3] point = ogr.Geometry(ogr.wkbPoint) point.AddPoint(random.uniform(xmin, xmax), random.uniform(ymin, ymax)) long = point.GetX() lat = point.GetY() random_point = ee.Geometry.Point([long, lat]) return random_point
def create_feature(self, layer, featureDict, expected_type, srs=None): created = False try: geom_dict = featureDict["geometry"] if not geom_dict: raise EsriFeatureLayerException("No Geometry Information") geom_type = geom_dict["type"] feature = ogr.Feature(layer.GetLayerDefn()) coords = self.get_geom_coords(geom_dict) f_json = json.dumps({"type": geom_type, "coordinates": coords}) geom = ogr.CreateGeometryFromJson(f_json) if geom and srs: geom.Transform(srs) if geom and expected_type != geom.GetGeometryType(): geom = ogr.ForceTo(geom, expected_type) if geom and expected_type == geom.GetGeometryType( ) and geom.IsValid(): feature.SetGeometry(geom) for prop, val in featureDict["properties"].items(): name = str(SLUGIFIER(prop)) value = val if value and layer.GetLayerDefn().GetFieldIndex( name) != -1: # replace id/code with mapped valued for subtypes if prop in self.esri_serializer.subtypes_fields: type_field_value = featureDict["properties"][ self.esri_serializer.subtype_field_name] # It is supposed to find the value, but check in case the data is not correct if value in self.esri_serializer.subtypes[ type_field_value][prop]: value = self.esri_serializer.subtypes[ type_field_value][prop][value] # It is supposed to find the value, but check in case the data is not correct elif prop in self.esri_serializer.fields_domains \ and value in self.esri_serializer.fields_domains[prop]: # replace id/code with mapped value for domain coded values value = self.esri_serializer.fields_domains[prop][ value] feature.SetField(name, value) created = layer.CreateFeature(feature) == ogr.OGRERR_NONE except Exception as e: logger.error('Failed to create feature', e) return created
def read_by_geom(self, wgs_geometry, tif_file): ''' 获取空间范围内的数据,在调用该函数之前先调用 info_by_geom 或 info_by_bbox,将返回的结果中的 tif_file 和 wgs_geometry 属性作为参数。 geom_info:矢量掩膜范围,必须包含 geometry 和 tif_file, geometry 必须为经纬度ogr.geometry的 wkt 或 geojson,例如: { 'wgs_geometry': 'POLYGON ((115.0 40.222408112063,115.0 40.3643188487053,115.312252122152 40.5,115.5 40.5,115.5 40.3046486467168,115.387540328212 40.2805104337424,115.0 40.222408112063))', 'tif_file': /mnt/LandsatGrids/LANDSAT/L5/121/44/2011/20110202/50_475/L5-TM-121-044-20110202-LSR-B2_50_475.tif } ''' # TODO: the format of wgs_geometry should be checked first # if len(wgs_geometry) > GEOM_MAX_SIZE: # raise EGeomTooLarge() if type(wgs_geometry) is ogr.Geometry: return self._read_by_geom(wgs_geometry, tif_file) else: wgs_geometry = ogr.CreateGeometryFromJson(wgs_geometry) return self._read_by_geom(wgs_geometry, tif_file)
def create_shape_from_json(id, json, output_directory): ''' Given a json string containing coordinates, this method creates a shape file. ''' create_directory_path(output_directory) filename = create_filename(output_directory, '%s.shp' % id) shape = Data(filename) if is_file(filename): shape.driver.DeleteDataSource(filename) data_source = shape.driver.CreateDataSource(filename) spatial_reference = osr.SpatialReference() spatial_reference.ImportFromEPSG(4326) layer = data_source.CreateLayer(str('layer'), spatial_reference, geom_type=ogr.wkbPolygon) layer.CreateField(ogr.FieldDefn(str('id'), ogr.OFTString)) feature = ogr.Feature(layer.GetLayerDefn()) feature.SetField(str('id'), str(id)) geometry = ogr.CreateGeometryFromJson(str(json)) feature.SetGeometry(geometry) layer.CreateFeature(feature) shape.close() return shape
def process_mask(name, mask_file, smpl=None): contour_file = f'{WORK_DIR}/{name}_countour.geojson' contour_wgs_file = f'{WORK_DIR}/{name}_countour_wgs.geojson' subprocess.call("gdal_contour -i 10 -f GeoJSON".split(' ') + [mask_file, contour_file]) simplify_opt = ["-simplify", f'{smpl}'] if smpl else [] subprocess.call([ "ogr2ogr", "-f", "GeoJSON", "-t_srs", "EPSG:4326", contour_wgs_file, contour_file ] + simplify_opt) with open(contour_wgs_file) as data_file: contours = json.load(data_file) features = contours['features'] good_features = [] for f in features: coords = f['geometry']['coordinates'] geom = {'type': 'Polygon', 'coordinates': [coords]} poly = ogr.CreateGeometryFromJson(json.dumps(geom)) area = poly.GetArea() good_features.append({ "type": "Feature", "geometry": geom, "properties": { "name": f'{len(good_features) + 1}' } }) store(f'{WORK_DIR}/{name}_final.geojson', { "type": "FeatureCollection", "features": good_features })
def storeinshp(osm_results, dst_shp): # create the new shp dr = ogr.GetDriverByName("ESRI Shapefile") ds = dr.CreateDataSource(dst_shp) sr = osr.SpatialReference() sr.SetFromUserInput('EPSG:4326') lyr = ds.CreateLayer("polygon", sr, ogr.wkbPolygon) for geojson in osm_results['features']: id = geojson['id'] geometry = geojson['geometry'] if geometry['type'] == 'LineString': geometry = { 'type': 'Polygon', 'coordinates': [geometry['coordinates']] } corner_points = json.dumps(geometry) # geom_json = json.dumps(geom_json) geom = ogr.CreateGeometryFromJson(corner_points) ffd = ogr.FeatureDefn() fgd = ogr.GeomFieldDefn() fgd.name = id fgd.type = ogr.wkbPolygon ffd.AddGeomFieldDefn(fgd) fpd = ogr.FieldDefn() fpd.name = geojson['properties'] fpd.type = ogr.OFTString ffd.AddFieldDefn(fpd) feat = ogr.Feature(ffd) feat.SetGeometry(geom) lyr.CreateFeature(feat)
def gen_zonalstats(zones_json, raster): """ Generator function that yields the statistics of a raster dataset within each polygon (zone) of a vector dataset. :param zones_json: Polygons in GeoJSON format :param raster: Raster dataset :return: Polygons with additional properties for calculated raster stats. """ # Open data raster = get_dataset(raster) if type(zones_json) is str: shp = ogr.Open(zones_json) zones_json = json.loads(zones_json) else: shp = ogr.Open(json.dumps(zones_json)) lyr = shp.GetLayer() # Get raster georeference info transform = raster.GetGeoTransform() xOrigin = transform[0] yOrigin = transform[3] pixelWidth = transform[1] pixelHeight = transform[5] # Reproject vector geometry to same projection as raster sourceSR = lyr.GetSpatialRef() targetSR = osr.SpatialReference() targetSR.ImportFromWkt(raster.GetProjectionRef()) coordTrans = osr.CoordinateTransformation(sourceSR, targetSR) # TODO: Use a multiprocessing pool to process features more quickly for feature in zones_json['features']: geom = ogr.CreateGeometryFromJson(json.dumps(feature['geometry'])) if sourceSR.ExportToWkt() != targetSR.ExportToWkt(): geom.Transform(coordTrans) # Get extent of feat if geom.GetGeometryName() == 'MULTIPOLYGON': count = 0 pointsX = [] pointsY = [] for polygon in geom: ring = geom.GetGeometryRef(count).GetGeometryRef(0) numpoints = ring.GetPointCount() for p in range(numpoints): lon, lat, z = ring.GetPoint(p) if abs(lon) != float('inf'): pointsX.append(lon) if abs(lat) != float('inf'): pointsY.append(lat) count += 1 elif geom.GetGeometryName() == 'POLYGON': ring = geom.GetGeometryRef(0) numpoints = ring.GetPointCount() pointsX = [] pointsY = [] for p in range(numpoints): lon, lat, z = ring.GetPoint(p) if abs(lon) != float('inf'): pointsX.append(lon) if abs(lat) != float('inf'): pointsY.append(lat) else: raise GaiaException( "ERROR: Geometry needs to be either Polygon or Multipolygon") xmin = min(pointsX) xmax = max(pointsX) ymin = min(pointsY) ymax = max(pointsY) # Specify offset and rows and columns to read xoff = int((xmin - xOrigin) / pixelWidth) yoff = int((yOrigin - ymax) / pixelWidth) xcount = int((xmax - xmin) / pixelWidth) + 1 ycount = int((ymax - ymin) / pixelWidth) + 1 # Create memory target raster target_ds = gdal.GetDriverByName('MEM').Create('', xcount, ycount, 1, gdal.GDT_Byte) target_ds.SetGeoTransform(( xmin, pixelWidth, 0, ymax, 0, pixelHeight, )) # Create for target raster the same projection as for the value raster raster_srs = osr.SpatialReference() raster_srs.ImportFromWkt(raster.GetProjectionRef()) target_ds.SetProjection(raster_srs.ExportToWkt()) # Rasterize zone polygon to raster gdal.RasterizeLayer(target_ds, [1], lyr, burn_values=[1]) # Read raster as arrays banddataraster = raster.GetRasterBand(1) try: dataraster = banddataraster.ReadAsArray(xoff, yoff, xcount, ycount).astype(numpy.float) except AttributeError: # Nothing within bounds, move on to next polygon properties = feature[u'properties'] for p in [ 'count', 'sum', 'mean', 'median', 'min', 'max', 'stddev' ]: properties[p] = None yield feature else: # Get no data value of array noDataValue = banddataraster.GetNoDataValue() if noDataValue: # Updata no data value in array with new value dataraster[dataraster == noDataValue] = numpy.nan bandmask = target_ds.GetRasterBand(1) datamask = bandmask.ReadAsArray(0, 0, xcount, ycount).astype(numpy.float) # Mask zone of raster zoneraster = numpy.ma.masked_array(dataraster, numpy.logical_not(datamask)) properties = feature['properties'] properties['count'] = zoneraster.count() properties['sum'] = numpy.nansum(zoneraster) if type(properties['sum']) == MaskedConstant: # No non-null values for raster data in polygon, skip for p in ['sum', 'mean', 'median', 'min', 'max', 'stddev']: properties[p] = None else: properties['mean'] = numpy.nanmean(zoneraster) properties['min'] = numpy.nanmin(zoneraster) properties['max'] = numpy.nanmax(zoneraster) properties['stddev'] = numpy.nanstd(zoneraster) median = numpy.ma.median(zoneraster) if hasattr(median, 'data') and not numpy.isnan(median.data): properties['median'] = median.data.item() yield (feature)
def gdal_clip(raster_input, raster_output, polygon_json, nodata=0): """ This function will subset a raster by a vector polygon. Adapted from the GDAL/OGR Python Cookbook at https://pcjericks.github.io/py-gdalogr-cookbook :param raster_input: raster input filepath :param raster_output: raster output filepath :param polygon_json: polygon as geojson string :param nodata: nodata value for output raster file :return: GDAL Dataset """ def image_to_array(i): """ Converts a Python Imaging Library array to a gdalnumeric image. """ a = gdalnumeric.numpy.fromstring(i.tobytes(), 'b') a.shape = i.im.size[1], i.im.size[0] return a def world_to_pixel(geoMatrix, x, y): """ Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate the pixel location of a geospatial coordinate """ ulX = geoMatrix[0] ulY = geoMatrix[3] xDist = geoMatrix[1] pixel = int((x - ulX) / xDist) line = int((ulY - y) / xDist) return (pixel, line) src_image = get_dataset(raster_input) # Load the source data as a gdalnumeric array src_array = src_image.ReadAsArray() src_dtype = src_array.dtype # Also load as a gdal image to get geotransform # (world file) info geo_trans = src_image.GetGeoTransform() nodata_values = [] for i in range(src_image.RasterCount): nodata_value = src_image.GetRasterBand(i + 1).GetNoDataValue() if not nodata_value: nodata_value = nodata nodata_values.append(nodata_value) # Create an OGR layer from a boundary GeoJSON geometry string if type(polygon_json) == dict: polygon_json = json.dumps(polygon_json) poly = ogr.CreateGeometryFromJson(polygon_json) # Convert the layer extent to image pixel coordinates min_x, max_x, min_y, max_y = poly.GetEnvelope() ul_x, ul_y = world_to_pixel(geo_trans, min_x, max_y) lr_x, lr_y = world_to_pixel(geo_trans, max_x, min_y) # Calculate the pixel size of the new image px_width = int(lr_x - ul_x) px_height = int(lr_y - ul_y) clip = src_array[ul_y:lr_y, ul_x:lr_x] # create pixel offset to pass to new image Projection info xoffset = ul_x yoffset = ul_y # Create a new geomatrix for the image geo_trans = list(geo_trans) geo_trans[0] = min_x geo_trans[3] = max_y # Map points to pixels for drawing the # boundary on a blank 8-bit, # black and white, mask image. raster_poly = Image.new("L", (px_width, px_height), 1) rasterize = ImageDraw.Draw(raster_poly) geometry_count = poly.GetGeometryCount() for i in range(0, geometry_count): points = [] pixels = [] pts = poly.GetGeometryRef(i) if pts.GetPointCount() == 0: pts = pts.GetGeometryRef(0) for p in range(pts.GetPointCount()): points.append((pts.GetX(p), pts.GetY(p))) for p in points: pixels.append(world_to_pixel(geo_trans, p[0], p[1])) rasterize.polygon(pixels, 0) mask = image_to_array(raster_poly) # Clip the image using the mask clip = gdalnumeric.numpy.choose(mask, (clip, nodata_value)).astype(src_dtype) # create output raster raster_band = raster_input.GetRasterBand(1) output_driver = gdal.GetDriverByName('MEM') output_dataset = output_driver.Create('', clip.shape[1], clip.shape[0], raster_input.RasterCount, raster_band.DataType) output_dataset.SetGeoTransform(geo_trans) output_dataset.SetProjection(raster_input.GetProjection()) gdalnumeric.CopyDatasetInfo(raster_input, output_dataset, xoff=xoffset, yoff=yoffset) bands = raster_input.RasterCount if bands > 1: for i in range(bands): outBand = output_dataset.GetRasterBand(i + 1) outBand.SetNoDataValue(nodata_values[i]) outBand.WriteArray(clip[i]) else: outBand = output_dataset.GetRasterBand(1) outBand.SetNoDataValue(nodata_values[0]) outBand.WriteArray(clip) if raster_output: output_driver = gdal.GetDriverByName('GTiff') outfile = output_driver.CreateCopy(raster_output, output_dataset, False) logger.debug(str(outfile)) outfile = None return output_dataset
def run_miningrehab_app(ds): """ Plots an interactive map of the mining case-study area and allows the user to draw polygons. This returns plots of the fractional cover value of bare soil, green vegetation and brown vegetation in the polygon area. Last modified: January 2020 inputs ds - data set containing masked Fractional Cover data from Landsat 8 """ # Suppress warnings warnings.filterwarnings("ignore") # Update plotting functionality through rcParams mpl.rcParams.update({"figure.autolayout": True}) # Define the bounding box that will be overlayed on the interactive map # The bounds are hard-coded to match those from the loaded data geom_obj = { "type": "Feature", "properties": { "style": { "stroke": True, "color": "red", "weight": 4, "opacity": 0.8, "fill": True, "fillColor": False, "fillOpacity": 0, "showArea": True, "clickable": True, } }, "geometry": { "type": "Polygon", "coordinates": [[ [116.630731, -34.434517], [116.630731, -34.426512], [116.648123, -34.426512], [116.648123, -34.434517], [116.630731, -34.434517], ]], }, } # Create a map geometry from the geom_obj dictionary # center specifies where the background map view should focus on # zoom specifies how zoomed in the background map should be loadeddata_geometry = ogr.CreateGeometryFromJson(str(geom_obj["geometry"])) loadeddata_center = [ loadeddata_geometry.Centroid().GetY(), loadeddata_geometry.Centroid().GetX(), ] loadeddata_zoom = 15 # define the study area map studyarea_map = Map( layout=widgets.Layout(width="480px", height="600px"), center=loadeddata_center, zoom=loadeddata_zoom, basemap=basemaps.Esri.WorldImagery, ) # define the drawing controls studyarea_drawctrl = DrawControl( polygon={"shapeOptions": { "fillOpacity": 0 }}, marker={}, circle={}, circlemarker={}, polyline={}, ) # add drawing controls and data bound geometry to the map studyarea_map.add_control(studyarea_drawctrl) studyarea_map.add_layer(GeoJSON(data=geom_obj)) # Index to count drawn polygons polygon_number = 0 # Define widgets to interact with instruction = widgets.Output(layout={"border": "1px solid black"}) with instruction: print("Draw a polygon within the red box to view plots of " "the fractional cover values of bare, green and " "non-green cover for the area over time.") info = widgets.Output(layout={"border": "1px solid black"}) with info: print("Plot status:") fig_display = widgets.Output(layout=widgets.Layout( width="50%" # proportion of horizontal space taken by plot )) with fig_display: plt.ioff() fig, ax = plt.subplots(3, 1, figsize=(9, 9)) for axis in ax: axis.set_ylim([0, 1]) colour_list = plt.rcParams["axes.prop_cycle"].by_key()["color"] # Function to execute each time something is drawn on the map def handle_draw(self, action, geo_json): nonlocal polygon_number # info.clear_output(wait=True) # wait=True reduces flicker effect # with info: # print("Plot status: entered handle draw") # Execute behaviour based on what the user draws if geo_json["geometry"]["type"] == "Polygon": # Convert the drawn geometry to pixel coordinates geom_selectedarea = transform_geojson_wgs_to_epsg( geo_json, EPSG=3577 # hard-coded to be same as case-study data ) # Construct a mask to only select pixels within the drawn polygon mask = rasterio.features.geometry_mask( [geom_selectedarea for geoms in [geom_selectedarea]], out_shape=ds.geobox.shape, transform=ds.geobox.affine, all_touched=False, invert=True, ) masked_ds = ds.where(mask) masked_ds_mean = masked_ds.mean(dim=["x", "y"], skipna=True) colour = colour_list[polygon_number % len(colour_list)] # Add a layer to the map to make the most recently drawn polygon # the same colour as the line on the plot studyarea_map.add_layer( GeoJSON( data=geo_json, style={ "color": colour, "opacity": 1, "weight": 4.5, "fillOpacity": 0.0, }, )) # Add Fractional cover plots to app masked_ds_mean.BS.interpolate_na( dim="time", method="nearest").plot.line("-", ax=ax[0]) masked_ds_mean.PV.interpolate_na( dim="time", method="nearest").plot.line("-", ax=ax[1]) masked_ds_mean.NPV.interpolate_na( dim="time", method="nearest").plot.line("-", ax=ax[2]) # reset titles back to custom ax[0].set_ylabel("Bare cover") ax[1].set_ylabel("Green cover") ax[2].set_ylabel("Non-green cover") # refresh display fig_display.clear_output( wait=True) # wait=True reduces flicker effect with fig_display: display(fig) # Update plot info info.clear_output(wait=True) # wait=True reduces flicker effect with info: print("Plot status: polygon added to plot") # Iterate the polygon number before drawing another polygon polygon_number = polygon_number + 1 else: info.clear_output(wait=True) with info: print("Plot status: this drawing tool is not currently " "supported. Please use the polygon tool.") # call to say activate handle_draw function on draw studyarea_drawctrl.on_draw(handle_draw) with fig_display: # TODO: update with user friendly something display(widgets.HTML("")) # Construct UI: # +-----------------------+ # | instruction | # +-----------+-----------+ # | map | plot | # | | | # +-----------+-----------+ # | info | # +-----------------------+ ui = widgets.VBox( [instruction, widgets.HBox([studyarea_map, fig_display]), info]) display(ui)
def onAddLayersClick(self): try: # On parcourt les champs géographiques recensés for geoField in self.connector.getGeoFields(): index = geoField["index"] type = geoField["type"] field = geoField["field"] geotype = geoField["geotype"] # On préparer les tableaux features = { "MultiPoint": [], "MultiLineString": [], "MultiPolygon": [] } # On parcourt les résultats hits = self.connector.getHits(index, type) if len(hits) > 0: # Si on va récupérer des geo_point if geotype == "geo_point": for hit in hits: try: # On construit une feature et on l'ajoute au tableau geoPoint = hit["_source"][field] wkt = "" if isinstance(geoPoint, str) or isinstance( geoPoint, unicode): coordinates = geoPoint.split(",") wkt = "POINT(" + coordinates[ 1] + " " + coordinates[0] + ")" elif isinstance(geoPoint, dict): wkt = "POINT(" + geoPoint[ "lon"] + " " + geoPoint["lat"] + ")" elif isinstance(geoPoint, list): wkt = "POINT(" + geoPoint[ 1] + " " + geoPoint[0] + ")" feature = QgsFeature() feature.setGeometry(QgsGeometry.fromWkt(wkt)) features["MultiPoint"].append(feature) except KeyError: pass # Si on va récupérer des geo_shape elif geotype == "geo_shape": for hit in hits: try: # On construit une feature et on l'ajoute au tableau geom = hit["_source"][field] geometry = ogr.CreateGeometryFromJson( json.dumps(geom)) wkt = geometry.ExportToWkt() feature = QgsFeature() feature.setGeometry(QgsGeometry.fromWkt(wkt)) geomtype = geom["type"].lower() if "point" in geomtype: features["MultiPoint"].append(feature) if "line" in geomtype: features["MultiLineString"].append(feature) if "polygon" in geomtype: features["MultiPolygon"].append(feature) except KeyError: pass # S'il y a au moins une géométrie exploitable qui a été récupérée dans ce champ if len(features["MultiPoint"]) + len( features["MultiLineString"]) + len( features["MultiPolygon"]) > 0: # On crée un groupe de couches name = "[@ " + self.connector.getUrl( ) + "] /" + index + "/" + type + "/" + field group = QgsProject.instance().layerTreeRoot().addGroup( name) # On crée les couches vectorielles et on les ajoute à la carte for geomtype in features: if len(features[geomtype]) > 0: # On crée la couche vectorielle layer = QgsVectorLayer( geomtype + "?crs=EPSG:4326", geomtype[5:] + "s", "memory") provider = layer.dataProvider() # On ajoute le tableau de features à la couche provider.addFeatures(features[geomtype]) layer.updateExtents() # On ajoute la couche au groupe QgsMapLayerRegistry.instance().addMapLayer( layer, False) group.addLayer(layer) self.connector.clearGeoFields() self.iface.messageBar().pushMessage( "ElasticSearch Connector", u"Les couches ont été ajoutées", level=QgsMessageBar.INFO, duration=5) # On ferme la popup self.oncloseDlgClick() except ESConnectorException, e: self.iface.messageBar().pushMessage("ElasticSearch Connector", str(e), level=QgsMessageBar.CRITICAL, duration=5)
wgs_geojson_moved = { 'coordinates': [corner_points_moved], 'type': 'Polygon' } wgs_geojson_moved = json.dumps(wgs_geojson_moved) # wgs to utm utm_geojson_moved = { 'coordinates': [wgs2utm.transform_points(corner_points_moved)], 'type': 'Polygon' } utm_geojson_moved = json.dumps(utm_geojson_moved) # 6 create polygon geometry wgs_geom = ogr.CreateGeometryFromJson(wgs_geojson_moved) wgs_geom_polygon = ogr.ForceToPolygon(wgs_geom) utm_geom = ogr.CreateGeometryFromJson(utm_geojson_moved) # 7 create feature wgs_feat = ogr.Feature(wgs_layerDefn) wgs_feat.SetGeometry(wgs_geom) wgs_feat.SetField('GridID', '%s_%s' % (zone, id)) # wgs_feat.SetGeomField('the_geom', wgs_geom) utm_feat = ogr.Feature(utm_layerDefn) utm_feat.SetGeometry(utm_geom) utm_feat.SetField('GridID', '%s_%s' % (zone, id)) # 8 save feature wgs_lyr.CreateFeature(wgs_feat)
def gen_zonalstats(zones_json, raster): # Open data raster = get_dataset(raster) shp = None if type(zones_json) is str: shp = ogr.Open(zones_json) zones_json = json.loads(zones_json) else: shp = ogr.Open(json.dumps(zones_json)) lyr = shp.GetLayer() # Get raster georeference info transform = raster.GetGeoTransform() xOrigin = transform[0] yOrigin = transform[3] pixelWidth = transform[1] pixelHeight = transform[5] # Reproject vector geometry to same projection as raster sourceSR = lyr.GetSpatialRef() targetSR = osr.SpatialReference() targetSR.ImportFromWkt(raster.GetProjectionRef()) coordTrans = osr.CoordinateTransformation(sourceSR, targetSR) for feature in zones_json['features']: geom = ogr.CreateGeometryFromJson(json.dumps(feature['geometry'])) geom.Transform(coordTrans) # Get extent of feat if (geom.GetGeometryName() == 'MULTIPOLYGON'): count = 0 pointsX = [] pointsY = [] for polygon in geom: geomInner = geom.GetGeometryRef(count) ring = geomInner.GetGeometryRef(0) numpoints = ring.GetPointCount() for p in range(numpoints): lon, lat, z = ring.GetPoint(p) pointsX.append(lon) pointsY.append(lat) count += 1 elif (geom.GetGeometryName() == 'POLYGON'): ring = geom.GetGeometryRef(0) numpoints = ring.GetPointCount() pointsX = [] pointsY = [] for p in range(numpoints): lon, lat, z = ring.GetPoint(p) pointsX.append(lon) pointsY.append(lat) else: raise GaiaException( "ERROR: Geometry needs to be either Polygon or Multipolygon") xmin = min(pointsX) xmax = max(pointsX) ymin = min(pointsY) ymax = max(pointsY) # Specify offset and rows and columns to read xoff = int((xmin - xOrigin) / pixelWidth) yoff = int((yOrigin - ymax) / pixelWidth) xcount = int((xmax - xmin) / pixelWidth) + 1 ycount = int((ymax - ymin) / pixelWidth) + 1 # Create memory target raster target_ds = gdal.GetDriverByName('MEM').Create('', xcount, ycount, 1, gdal.GDT_Byte) target_ds.SetGeoTransform(( xmin, pixelWidth, 0, ymax, 0, pixelHeight, )) # Create for target raster the same projection as for the value raster raster_srs = osr.SpatialReference() raster_srs.ImportFromWkt(raster.GetProjectionRef()) target_ds.SetProjection(raster_srs.ExportToWkt()) # Rasterize zone polygon to raster gdal.RasterizeLayer(target_ds, [1], lyr, burn_values=[1]) # Read raster as arrays banddataraster = raster.GetRasterBand(1) dataraster = banddataraster.ReadAsArray(xoff, yoff, xcount, ycount).astype(numpy.float) bandmask = target_ds.GetRasterBand(1) datamask = bandmask.ReadAsArray(0, 0, xcount, ycount).astype(numpy.float) # Mask zone of raster zoneraster = numpy.ma.masked_array(dataraster, numpy.logical_not(datamask)) properties = feature['properties'] properties['count'] = zoneraster.count() properties['sum'] = zoneraster.sum() properties['mean'] = zoneraster.mean() properties['median'] = numpy.median(zoneraster) properties['min'] = zoneraster.min() properties['max'] = zoneraster.max() properties['stddev'] = zoneraster.std() yield (feature)
def sample(raster, input, output, n_samples, epsg=3310): ''' :param raster: the raster data from which sample will be taken :param input: boundary of the sample area :param output: location of sample points :param n_samples: samples taken from the pixels :return: Data Frame ''' # check data type dataType = os.path.basename(input).split('.')[1] if dataType == "shp": driver = ogr.GetDriverByName("ESRI Shapefile") file = driver.Open(input, 0) layer = file.GetLayer() env = layer.GetExtent() polygon = ogr.Geometry(ogr.wkbGeometryCollection) xmin, ymin, xmax, ymax = env[0], env[2], env[1], env[3] for feature in layer: geom = feature.GetGeometryRef() ring = geom.GetGeometryRef(0) polygon.AddGeometry(ring) else: #get boundary values from json with open(input) as f: data = json.load(f) for feature in data['features']: geom = feature['geometry'] geom = json.dumps(geom) polygon = ogr.CreateGeometryFromJson(geom) env = polygon.GetEnvelope() xmin, ymin, xmax, ymax = env[0], env[2], env[1], env[3] # Read raster src_ds = gdal.Open(raster) geoT = src_ds.GetGeoTransform() num_points = n_samples counter = 0 rows = [] # write random points to vector-point multipoint = ogr.Geometry(ogr.wkbMultiPoint) outDriver = ogr.GetDriverByName("ESRI Shapefile") outDataSource = outDriver.CreateDataSource(output) outLayer = outDataSource.CreateLayer(output, geom_type=ogr.wkbPoint) for i in range(0, num_points): i += 1 ''' If random point (i) is inside the boundary: store the location and extract pixel values ''' point = ogr.Geometry(ogr.wkbPoint) point.AddPoint(random.uniform(xmin, xmax), random.uniform(ymin, ymax)) if point.Within(polygon): multipoint.AddGeometry(point) counter += 1 featureDefn = outLayer.GetLayerDefn() outFeature = ogr.Feature(featureDefn) outFeature.SetGeometry(point) outLayer.CreateFeature(outFeature) mx, my = point.GetX(), point.GetY() px = int((mx - geoT[0]) / geoT[1]) py = int((my - geoT[3]) / geoT[5]) xcount = 1 ycount = 1 ext = [] # Extract pixels values for all bands for i in range(0, src_ds.RasterCount): i += 1 dump = src_ds.GetRasterBand(i).ReadAsArray(px, py, xcount, ycount) extract = [x for x in dump if x != None] result = extract[0] ext.append(result[0]) rows.append(ext) # Return data frame df = pd.DataFrame(rows) # Create projection (prj file) spatialRef = osr.SpatialReference() spatialRef.ImportFromEPSG(epsg) spatialRef.MorphToESRI() prj_full_path = os.path.split(output) prj_path = os.path.split(output)[0] prj_file_name = os.path.split(output)[1] prj_full_path = os.path.basename(output).split('.')[0] k = prj_full_path + '.prj' file = open(k, 'w') r = os.path.join(prj_path, k) file = open(r, 'w') file.write(spatialRef.ExportToWkt()) file.close() # write to csv text = prj_full_path + '.txt' r = os.path.join(prj_path, text) df.to_csv(r) return df