def addLengthMeters(self, stream_network): """ Adds length field in meters to network (The added field name will be 'LENGTH_M'). .. note:: This may be needed for generating the kfac file depending on the units of your raster. See: :doc:`gis_tools`. Parameters: stream_network(str): Path to stream network file. Here is an example of how to use this: .. code:: python import os from RAPIDpy.gis.taudem import TauDEM td = TauDEM() output_directory = '/path/to/output/files' td.addLengthMeters(os.path.join(output_directory,"stream_reach_file.shp")) """ network_shapefile = ogr.Open(stream_network, 1) network_layer = network_shapefile.GetLayer() network_layer_defn = network_layer.GetLayerDefn() #make sure projection EPSG:4326 network_layer_proj = network_layer.GetSpatialRef() geographic_proj = osr.SpatialReference() geographic_proj.ImportFromEPSG(4326) proj_transform = None if network_layer_proj != geographic_proj: proj_transform = osr.CoordinateTransformation( network_layer_proj, geographic_proj) #check for field create_field = True for i in xrange(network_layer_defn.GetFieldCount()): field_name = network_layer_defn.GetFieldDefn(i).GetName() if field_name == 'LENGTH_M': create_field = False break if create_field: network_layer.CreateField(ogr.FieldDefn('LENGTH_M', ogr.OFTReal)) geo_manager = Geod(ellps="WGS84") for network_feature in network_layer: feat_geom = network_feature.GetGeometryRef() #make sure coordinates are geographic if proj_transform: feat_geom.Transform(proj_transform) line = shapely_loads(feat_geom.ExportToWkb()) lon_list, lat_list = line.xy az1, az2, dist = geo_manager.inv(lon_list[:-1], lat_list[:-1], lon_list[1:], lat_list[1:]) network_feature.SetField('LENGTH_M', sum(dist)) network_layer.SetFeature(network_feature)
def addLengthMeters(self, stream_network): """ Adds length field in meters to network (The added field name will be 'LENGTH_M'). .. note:: This may be needed for generating the kfac file depending on the units of your raster. See: :doc:`gis_tools`. Parameters: stream_network(str): Path to stream network file. Here is an example of how to use this: .. code:: python import os from RAPIDpy.gis.taudem import TauDEM td = TauDEM() output_directory = '/path/to/output/files' td.addLengthMeters(os.path.join(output_directory,"stream_reach_file.shp")) """ network_shapefile = ogr.Open(stream_network, 1) network_layer = network_shapefile.GetLayer() network_layer_defn = network_layer.GetLayerDefn() #make sure projection EPSG:4326 network_layer_proj = network_layer.GetSpatialRef() geographic_proj = osr.SpatialReference() geographic_proj.ImportFromEPSG(4326) proj_transform = None if network_layer_proj != geographic_proj: proj_transform = osr.CoordinateTransformation(network_layer_proj, geographic_proj) #check for field create_field=True for i in xrange(network_layer_defn.GetFieldCount()): field_name = network_layer_defn.GetFieldDefn(i).GetName() if field_name == 'LENGTH_M': create_field=False break if create_field: network_layer.CreateField(ogr.FieldDefn('LENGTH_M', ogr.OFTReal)) geo_manager = Geod(ellps="WGS84") for network_feature in network_layer: feat_geom = network_feature.GetGeometryRef() #make sure coordinates are geographic if proj_transform: feat_geom.Transform(proj_transform) line = shapely_loads(feat_geom.ExportToWkb()) lon_list, lat_list = line.xy az1, az2, dist = geo_manager.inv(lon_list[:-1], lat_list[:-1], lon_list[1:], lat_list[1:]) network_feature.SetField('LENGTH_M', sum(dist)) network_layer.SetFeature(network_feature)
def rasterToPolygon(self, raster_file, polygon_file): """ Converts raster to polygon and then dissolves it """ print("Process: Raster to Polygon ...") time_start = datetime.utcnow() temp_polygon_file = "{0}_temp.shp".format(os.path.splitext(os.path.basename(polygon_file))[0]) cmd = ["gdal_polygonize.py", raster_file, "-f", "ESRI Shapefile", temp_polygon_file, os.path.splitext(os.path.basename(temp_polygon_file))[0], "LINKNO"] process = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False) out, err = process.communicate() if out: print("OUTPUT:") for line in out.split(b'\n'): print(line) if err: print("ERROR:") print(err) #raise Exception(err) print("Time to convert to polygon: {0}".format(datetime.utcnow()-time_start)) print("Dissolving ...") time_start_dissolve = datetime.utcnow() ogr_polygin_shapefile = ogr.Open(temp_polygon_file) ogr_polygon_shapefile_lyr = ogr_polygin_shapefile.GetLayer() number_of_features = ogr_polygon_shapefile_lyr.GetFeatureCount() polygon_rivid_list = np.zeros(number_of_features, dtype=np.int32) for feature_idx, catchment_feature in enumerate(ogr_polygon_shapefile_lyr): polygon_rivid_list[feature_idx] = catchment_feature.GetField('LINKNO') shp_drv = ogr.GetDriverByName('ESRI Shapefile') # Remove output shapefile if it already exists if os.path.exists(polygon_file): shp_drv.DeleteDataSource(polygon_file) dissolve_shapefile = shp_drv.CreateDataSource(polygon_file) dissolve_layer = dissolve_shapefile.CreateLayer('', ogr_polygon_shapefile_lyr.GetSpatialRef(), ogr.wkbPolygon) dissolve_layer.CreateField(ogr.FieldDefn('LINKNO', ogr.OFTInteger)) dissolve_layer_defn = dissolve_layer.GetLayerDefn() for unique_rivid in np.unique(polygon_rivid_list): #get indices where it is in the polygon feature_indices = np.where(polygon_rivid_list==unique_rivid)[0] new_feat = ogr.Feature(dissolve_layer_defn) new_feat.SetField('LINKNO', int(unique_rivid)) if len(feature_indices) == 1: ##write feature to file feature = ogr_polygon_shapefile_lyr.GetFeature(feature_indices[0]) new_feat.SetGeometry(feature.GetGeometryRef()) else: ##dissolve dissolve_poly_list = [] for feature_index in feature_indices: feature = ogr_polygon_shapefile_lyr.GetFeature(feature_index) feat_geom = feature.GetGeometryRef() dissolve_poly_list.append(shapely_loads(feat_geom.ExportToWkb())) dissolve_polygon = cascaded_union(dissolve_poly_list) new_feat.SetGeometry(ogr.CreateGeometryFromWkb(dissolve_polygon.wkb)) dissolve_layer.CreateFeature(new_feat) #clean up shp_drv.DeleteDataSource(temp_polygon_file) print("Time to dissolve: {0}".format(datetime.utcnow()-time_start_dissolve)) print("Total time to convert: {0}".format(datetime.utcnow()-time_start))
def RTreeCreateWeightTable(lsm_grid_lat, lsm_grid_lon, in_catchment_shapefile, river_id, in_rapid_connect, out_weight_table, file_geodatabase=None, area_id=None): """ Create Weight Table for Land Surface Model Grids """ time_start_all = datetime.utcnow() print("Generating LSM Grid Thiessen Array ...") if file_geodatabase: gdb_driver = ogr.GetDriverByName("OpenFileGDB") ogr_file_geodatabase = gdb_driver.Open(file_geodatabase, 0) ogr_catchment_shapefile_lyr = ogr_file_geodatabase.GetLayer( in_catchment_shapefile) else: ogr_catchment_shapefile = ogr.Open(in_catchment_shapefile) ogr_catchment_shapefile_lyr = ogr_catchment_shapefile.GetLayer() ogr_catchment_shapefile_lyr_proj = ogr_catchment_shapefile_lyr.GetSpatialRef( ) original_catchment_proj = Proj( ogr_catchment_shapefile_lyr_proj.ExportToProj4()) geographic_proj = Proj(init='EPSG:4326') #geographic extent = ogr_catchment_shapefile_lyr.GetExtent() if original_catchment_proj != geographic_proj: x, y = transform(original_catchment_proj, geographic_proj, [extent[0], extent[1]], [extent[2], extent[3]]) extent = [min(x), max(x), min(y), max(y)] lsm_grid_feature_list = pointsToVoronoiGridArray(lsm_grid_lat, lsm_grid_lon, extent) ##COMMENTED LINES FOR TESTING ##import os ##from .voronoi import pointsToVoronoiGridShapefile ##vor_shp_path = os.path.join(os.path.dirname(in_catchment_shapefile), "test_grid.shp") ##pointsToVoronoiGridShapefile(lsm_grid_lat, lsm_grid_lon, vor_shp_path, extent) time_end_lsm_grid_thiessen = datetime.utcnow() print(time_end_lsm_grid_thiessen - time_start_all) print("Generating LSM Grid Rtree ...") rtree_idx = rtree.index.Index() # Populate R-tree index with bounds of ECMWF grid cells for lsm_grid_pos, lsm_grid_feature in enumerate(lsm_grid_feature_list): rtree_idx.insert(lsm_grid_pos, lsm_grid_feature['polygon'].bounds) time_end_lsm_grid_rtree = datetime.utcnow() print(time_end_lsm_grid_rtree - time_end_lsm_grid_thiessen) print("Retrieving catchment river id list ...") number_of_catchment_features = ogr_catchment_shapefile_lyr.GetFeatureCount( ) catchment_rivid_list = np.zeros(number_of_catchment_features, dtype=np.int32) for feature_idx, catchment_feature in enumerate( ogr_catchment_shapefile_lyr): catchment_rivid_list[feature_idx] = catchment_feature.GetField( river_id) print("Reading in RAPID connect file ...") rapid_connect_rivid_list = get_rivid_list_from_file(in_rapid_connect) print("Find LSM grid cells that intersect with each catchment") print("and write out weight table ...") dummy_lat_index, dummy_lon_index = _get_lat_lon_indices( lsm_grid_lat, lsm_grid_lon, lsm_grid_feature_list[0]['lat'], lsm_grid_feature_list[0]['lon']) dummy_row_end = [ 0, dummy_lon_index, dummy_lat_index, 1, lsm_grid_feature_list[0]['lon'], lsm_grid_feature_list[0]['lat'] ] with open_csv(out_weight_table, 'w') as csvfile: connectwriter = csv.writer(csvfile) connectwriter.writerow([ 'rivid', 'area_sqm', 'lon_index', 'lat_index', 'npoints', 'lsm_grid_lon', 'lsm_grid_lat' ]) geographic_proj = Proj(init='EPSG:4326') #geographic osr_geographic_proj = osr.SpatialReference() osr_geographic_proj.ImportFromEPSG(4326) proj_transform = None if original_catchment_proj != geographic_proj: proj_transform = osr.CoordinateTransformation( ogr_catchment_shapefile_lyr_proj, osr_geographic_proj) for rapid_connect_rivid in rapid_connect_rivid_list: intersect_grid_info_list = [] try: catchment_pos = np.where( catchment_rivid_list == rapid_connect_rivid)[0][0] except IndexError: #if it is not in the catchment, add dummy row in its place connectwriter.writerow([rapid_connect_rivid] + dummy_row_end) continue pass get_catchment_feature = ogr_catchment_shapefile_lyr.GetFeature( catchment_pos) feat_geom = get_catchment_feature.GetGeometryRef() #make sure coordinates are geographic if proj_transform: feat_geom.Transform(proj_transform) catchment_polygon = shapely_loads(feat_geom.ExportToWkb()) for sub_lsm_grid_pos in rtree_idx.intersection( catchment_polygon.bounds): if catchment_polygon.intersects( lsm_grid_feature_list[sub_lsm_grid_pos]['polygon']): intersect_poly = catchment_polygon.intersection( lsm_grid_feature_list[sub_lsm_grid_pos]['polygon']) if not area_id: #attempt to calculate AREA poly_area = get_poly_area_geo(intersect_poly) else: poly_area = float( catchment_polygon.GetFeature(area_id) ) * intersect_poly.area / catchment_polygon.area index_lsm_grid_lat, index_lsm_grid_lon = _get_lat_lon_indices( lsm_grid_lat, lsm_grid_lon, lsm_grid_feature_list[sub_lsm_grid_pos]['lat'], lsm_grid_feature_list[sub_lsm_grid_pos]['lon']) intersect_grid_info_list.append({ 'rivid': rapid_connect_rivid, 'area': poly_area, 'lsm_grid_lat': lsm_grid_feature_list[sub_lsm_grid_pos]['lat'], 'lsm_grid_lon': lsm_grid_feature_list[sub_lsm_grid_pos]['lon'], 'index_lsm_grid_lon': index_lsm_grid_lon, 'index_lsm_grid_lat': index_lsm_grid_lat }) npoints = len(intersect_grid_info_list) for intersect_grid_info in intersect_grid_info_list: connectwriter.writerow([ intersect_grid_info['rivid'], intersect_grid_info['area'], intersect_grid_info['index_lsm_grid_lon'], intersect_grid_info['index_lsm_grid_lat'], npoints, intersect_grid_info['lsm_grid_lon'], intersect_grid_info['lsm_grid_lat'] ]) time_end_all = datetime.utcnow() print(time_end_all - time_end_lsm_grid_rtree) print("TOTAL TIME: {0}".format(time_end_all - time_start_all))
def rasterToPolygon(self, raster_file, polygon_file): """ Converts raster to polygon and then dissolves it """ print("Process: Raster to Polygon ...") time_start = datetime.utcnow() temp_polygon_file = "{0}_temp.shp".format( os.path.splitext(os.path.basename(polygon_file))[0]) cmd = [ "gdal_polygonize.py", raster_file, "-f", "ESRI Shapefile", temp_polygon_file, os.path.splitext(os.path.basename(temp_polygon_file))[0], "LINKNO" ] process = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=False) out, err = process.communicate() if out: print("OUTPUT:") for line in out.split(b'\n'): print(line) if err: print("ERROR:") print(err) #raise Exception(err) print("Time to convert to polygon: {0}".format(datetime.utcnow() - time_start)) print("Dissolving ...") time_start_dissolve = datetime.utcnow() ogr_polygin_shapefile = ogr.Open(temp_polygon_file) ogr_polygon_shapefile_lyr = ogr_polygin_shapefile.GetLayer() number_of_features = ogr_polygon_shapefile_lyr.GetFeatureCount() polygon_rivid_list = np.zeros(number_of_features, dtype=np.int32) for feature_idx, catchment_feature in enumerate( ogr_polygon_shapefile_lyr): polygon_rivid_list[feature_idx] = catchment_feature.GetField( 'LINKNO') shp_drv = ogr.GetDriverByName('ESRI Shapefile') # Remove output shapefile if it already exists if os.path.exists(polygon_file): shp_drv.DeleteDataSource(polygon_file) dissolve_shapefile = shp_drv.CreateDataSource(polygon_file) dissolve_layer = dissolve_shapefile.CreateLayer( '', ogr_polygon_shapefile_lyr.GetSpatialRef(), ogr.wkbPolygon) dissolve_layer.CreateField(ogr.FieldDefn('LINKNO', ogr.OFTInteger)) dissolve_layer_defn = dissolve_layer.GetLayerDefn() for unique_rivid in np.unique(polygon_rivid_list): #get indices where it is in the polygon feature_indices = np.where(polygon_rivid_list == unique_rivid)[0] new_feat = ogr.Feature(dissolve_layer_defn) new_feat.SetField('LINKNO', int(unique_rivid)) if len(feature_indices) == 1: ##write feature to file feature = ogr_polygon_shapefile_lyr.GetFeature( feature_indices[0]) new_feat.SetGeometry(feature.GetGeometryRef()) else: ##dissolve dissolve_poly_list = [] for feature_index in feature_indices: feature = ogr_polygon_shapefile_lyr.GetFeature( feature_index) feat_geom = feature.GetGeometryRef() dissolve_poly_list.append( shapely_loads(feat_geom.ExportToWkb())) dissolve_polygon = cascaded_union(dissolve_poly_list) new_feat.SetGeometry( ogr.CreateGeometryFromWkb(dissolve_polygon.wkb)) dissolve_layer.CreateFeature(new_feat) #clean up shp_drv.DeleteDataSource(temp_polygon_file) print("Time to dissolve: {0}".format(datetime.utcnow() - time_start_dissolve)) print("Total time to convert: {0}".format(datetime.utcnow() - time_start))
def rtree_create_weight_table(lsm_grid_lat, lsm_grid_lon, in_catchment_shapefile, river_id, in_rapid_connect, out_weight_table, file_geodatabase=None, area_id=None, lsm_grid_mask=None): """ Create Weight Table for Land Surface Model Grids """ time_start_all = datetime.utcnow() if lsm_grid_lat.ndim == 3 and lsm_grid_lon.ndim == 3: # assume first dimension is time lsm_grid_lat = lsm_grid_lat[0] lsm_grid_lon = lsm_grid_lon[0] log("Generating LSM Grid Thiessen Array ...") if file_geodatabase: gdb_driver = ogr.GetDriverByName("OpenFileGDB") ogr_file_geodatabase = gdb_driver.Open(file_geodatabase, 0) ogr_catchment_shapefile_lyr = \ ogr_file_geodatabase.GetLayer(in_catchment_shapefile) else: ogr_catchment_shapefile = ogr.Open(in_catchment_shapefile) ogr_catchment_shapefile_lyr = ogr_catchment_shapefile.GetLayer() ogr_catchment_shapefile_lyr_proj = \ ogr_catchment_shapefile_lyr.GetSpatialRef() original_catchment_proj = \ Proj(ogr_catchment_shapefile_lyr_proj.ExportToProj4()) geographic_proj = Proj(init='EPSG:4326') extent = ogr_catchment_shapefile_lyr.GetExtent() if original_catchment_proj != geographic_proj: x, y = transform(original_catchment_proj, geographic_proj, [extent[0], extent[1]], [extent[2], extent[3]]) extent = [min(x), max(x), min(y), max(y)] lsm_grid_feature_list = \ pointsToVoronoiGridArray(lsm_grid_lat, lsm_grid_lon, extent) # ##COMMENTED LINES FOR TESTING # import os # from .voronoi import pointsToVoronoiGridShapefile # vor_shp_path = \ # os.path.join(os.path.dirname(in_catchment_shapefile), "test_grid.shp") # pointsToVoronoiGridShapefile(lsm_grid_lat, lsm_grid_lon, # vor_shp_path, extent) time_end_lsm_grid_thiessen = datetime.utcnow() log(time_end_lsm_grid_thiessen - time_start_all) log("Generating LSM Grid Rtree ...") rtree_idx = rtree.index.Index() # Populate R-tree index with bounds of ECMWF grid cells for lsm_grid_pos, lsm_grid_feature in enumerate(lsm_grid_feature_list): rtree_idx.insert(lsm_grid_pos, lsm_grid_feature['polygon'].bounds) time_end_lsm_grid_rtree = datetime.utcnow() log(time_end_lsm_grid_rtree - time_end_lsm_grid_thiessen) log("Retrieving catchment river id list ...") number_of_catchment_features = \ ogr_catchment_shapefile_lyr.GetFeatureCount() catchment_rivid_list = \ np.zeros(number_of_catchment_features, dtype=np.int32) for feature_idx, catchment_feature in \ enumerate(ogr_catchment_shapefile_lyr): catchment_rivid_list[feature_idx] = \ catchment_feature.GetField(river_id) log("Reading in RAPID connect file ...") rapid_connect_rivid_list = np.loadtxt(in_rapid_connect, delimiter=",", usecols=(0, ), ndmin=1, dtype=int) log("Find LSM grid cells that intersect with each catchment") log("and write out weight table ...") dummy_lat_index, dummy_lon_index = \ _get_lat_lon_indices(lsm_grid_lat, lsm_grid_lon, lsm_grid_feature_list[0]['lat'], lsm_grid_feature_list[0]['lon']) dummy_row_end = [ 0, dummy_lon_index, dummy_lat_index, 1, lsm_grid_feature_list[0]['lon'], lsm_grid_feature_list[0]['lat'] ] with open_csv(out_weight_table, 'w') as csvfile: connectwriter = csv.writer(csvfile) connectwriter.writerow([ 'rivid', 'area_sqm', 'lon_index', 'lat_index', 'npoints', 'lsm_grid_lon', 'lsm_grid_lat' ]) geographic_proj = Proj(init='EPSG:4326') osr_geographic_proj = osr.SpatialReference() osr_geographic_proj.ImportFromEPSG(4326) proj_transform = None if original_catchment_proj != geographic_proj: proj_transform = \ osr.CoordinateTransformation(ogr_catchment_shapefile_lyr_proj, osr_geographic_proj) for rapid_connect_rivid in rapid_connect_rivid_list: intersect_grid_info_list = [] try: catchment_pos = \ np.where(catchment_rivid_list == rapid_connect_rivid)[0][0] except IndexError: # if it is not in the catchment, add dummy row in its place connectwriter.writerow([rapid_connect_rivid] + dummy_row_end) continue get_catchment_feature = \ ogr_catchment_shapefile_lyr.GetFeature(catchment_pos) feat_geom = get_catchment_feature.GetGeometryRef() # make sure coordinates are geographic if proj_transform: feat_geom.Transform(proj_transform) catchment_polygon = shapely_loads(feat_geom.ExportToWkb()) for sub_lsm_grid_pos in \ rtree_idx.intersection(catchment_polygon.bounds): lsm_grid_polygon = \ lsm_grid_feature_list[sub_lsm_grid_pos]['polygon'] if catchment_polygon.intersects(lsm_grid_polygon): try: intersect_poly = \ catchment_polygon.intersection(lsm_grid_polygon) except TopologicalError: log('The catchment polygon with id {0} was ' 'invalid. Attempting to self clean...'.format( rapid_connect_rivid)) original_area = catchment_polygon.area catchment_polygon = catchment_polygon.buffer(0) area_ratio = original_area / catchment_polygon.area log('AREA_RATIO: {0}'.format(area_ratio)) msg_level = "INFO" if round(area_ratio, 5) != 1: msg_level = "WARNING" log('The cleaned catchment polygon area ' 'differs from the original area by {0}%.'.format( abs(area_ratio - 1)), severity=msg_level) intersect_poly = \ catchment_polygon.intersection(lsm_grid_polygon) if not area_id: # attempt to calculate AREA poly_area = get_poly_area_geo(intersect_poly) else: poly_area = \ float(get_catchment_feature.GetField(area_id)) * \ intersect_poly.area/catchment_polygon.area index_lsm_grid_lat, index_lsm_grid_lon = \ _get_lat_lon_indices( lsm_grid_lat, lsm_grid_lon, lsm_grid_feature_list[sub_lsm_grid_pos]['lat'], lsm_grid_feature_list[sub_lsm_grid_pos]['lon']) if lsm_grid_mask is not None: if lsm_grid_mask[int(index_lsm_grid_lat), int(index_lsm_grid_lon)] > 0: poly_area /= lsm_grid_mask[int(index_lsm_grid_lat), int(index_lsm_grid_lon)] intersect_grid_info_list.append({ 'rivid': rapid_connect_rivid, 'area': poly_area, 'lsm_grid_lat': lsm_grid_feature_list[sub_lsm_grid_pos]['lat'], 'lsm_grid_lon': lsm_grid_feature_list[sub_lsm_grid_pos]['lon'], 'index_lsm_grid_lon': index_lsm_grid_lon, 'index_lsm_grid_lat': index_lsm_grid_lat }) npoints = len(intersect_grid_info_list) # If no intersection found, add dummy row if npoints <= 0: connectwriter.writerow([rapid_connect_rivid] + dummy_row_end) for intersect_grid_info in intersect_grid_info_list: connectwriter.writerow([ intersect_grid_info['rivid'], intersect_grid_info['area'], intersect_grid_info['index_lsm_grid_lon'], intersect_grid_info['index_lsm_grid_lat'], npoints, intersect_grid_info['lsm_grid_lon'], intersect_grid_info['lsm_grid_lat'] ]) time_end_all = datetime.utcnow() log(time_end_all - time_end_lsm_grid_rtree) log("TOTAL TIME: {0}".format(time_end_all - time_start_all))
def rasterToPolygon(raster_file, polygon_file): """ Converts watershed raster to polygon and then dissolves it. It dissolves features based on the LINKNO attribute. """ log("Process: Raster to Polygon ...") time_start = datetime.utcnow() temp_polygon_file = \ "{0}_temp.shp".format( os.path.splitext(os.path.basename(polygon_file))[0]) GDALGrid(raster_file).to_polygon(out_shapefile=temp_polygon_file, fieldname="LINKNO", self_mask=True) log("Time to convert to polygon: {0}".format(datetime.utcnow() - time_start)) log("Dissolving ...") time_start_dissolve = datetime.utcnow() ogr_polygin_shapefile = ogr.Open(temp_polygon_file) ogr_polygon_shapefile_lyr = ogr_polygin_shapefile.GetLayer() number_of_features = ogr_polygon_shapefile_lyr.GetFeatureCount() polygon_rivid_list = np.zeros(number_of_features, dtype=np.int32) for feature_idx, catchment_feature in \ enumerate(ogr_polygon_shapefile_lyr): polygon_rivid_list[feature_idx] = \ catchment_feature.GetField('LINKNO') shp_drv = ogr.GetDriverByName('ESRI Shapefile') # Remove output shapefile if it already exists if os.path.exists(polygon_file): shp_drv.DeleteDataSource(polygon_file) dissolve_shapefile = shp_drv.CreateDataSource(polygon_file) dissolve_layer = \ dissolve_shapefile.CreateLayer( '', ogr_polygon_shapefile_lyr.GetSpatialRef(), ogr.wkbPolygon) dissolve_layer.CreateField(ogr.FieldDefn('LINKNO', ogr.OFTInteger)) dissolve_layer_defn = dissolve_layer.GetLayerDefn() for unique_rivid in np.unique(polygon_rivid_list): # get indices where it is in the polygon feature_indices = np.where(polygon_rivid_list == unique_rivid)[0] new_feat = ogr.Feature(dissolve_layer_defn) new_feat.SetField('LINKNO', int(unique_rivid)) if len(feature_indices) == 1: # write feature to file feature = \ ogr_polygon_shapefile_lyr.GetFeature(feature_indices[0]) new_feat.SetGeometry(feature.GetGeometryRef()) else: # dissolve dissolve_poly_list = [] for feature_index in feature_indices: feature = \ ogr_polygon_shapefile_lyr.GetFeature(feature_index) feat_geom = feature.GetGeometryRef() dissolve_poly_list.append( shapely_loads(feat_geom.ExportToWkb())) dissolve_polygon = cascaded_union(dissolve_poly_list) new_feat.SetGeometry( ogr.CreateGeometryFromWkb(dissolve_polygon.wkb)) dissolve_layer.CreateFeature(new_feat) # clean up shp_drv.DeleteDataSource(temp_polygon_file) log("Time to dissolve: {0}".format(datetime.utcnow() - time_start_dissolve)) log("Total time to convert: {0}".format(datetime.utcnow() - time_start))
def RTreeCreateWeightTable(lsm_grid_lat, lsm_grid_lon, in_catchment_shapefile, river_id, in_rapid_connect, out_weight_table, file_geodatabase=None, area_id=None): """ Create Weight Table for Land Surface Model Grids """ time_start_all = datetime.utcnow() if lsm_grid_lat.ndim == 3 and lsm_grid_lon.ndim == 3: #assume first dimension is time lsm_grid_lat = lsm_grid_lat[0] lsm_grid_lon = lsm_grid_lon[0] print("Generating LSM Grid Thiessen Array ...") if file_geodatabase: gdb_driver = ogr.GetDriverByName("OpenFileGDB") ogr_file_geodatabase = gdb_driver.Open(file_geodatabase, 0) ogr_catchment_shapefile_lyr = ogr_file_geodatabase.GetLayer(in_catchment_shapefile) else: ogr_catchment_shapefile = ogr.Open(in_catchment_shapefile) ogr_catchment_shapefile_lyr = ogr_catchment_shapefile.GetLayer() ogr_catchment_shapefile_lyr_proj = ogr_catchment_shapefile_lyr.GetSpatialRef() original_catchment_proj = Proj(ogr_catchment_shapefile_lyr_proj.ExportToProj4()) geographic_proj = Proj(init='EPSG:4326') #geographic extent = ogr_catchment_shapefile_lyr.GetExtent() if original_catchment_proj != geographic_proj: x, y = transform(original_catchment_proj, geographic_proj, [extent[0], extent[1]], [extent[2], extent[3]]) extent = [min(x), max(x), min(y), max(y)] lsm_grid_feature_list = pointsToVoronoiGridArray(lsm_grid_lat, lsm_grid_lon, extent) ##COMMENTED LINES FOR TESTING # import os # from .voronoi import pointsToVoronoiGridShapefile # vor_shp_path = os.path.join(os.path.dirname(in_catchment_shapefile), "test_grid.shp") # pointsToVoronoiGridShapefile(lsm_grid_lat, lsm_grid_lon, vor_shp_path, extent) time_end_lsm_grid_thiessen = datetime.utcnow() print(time_end_lsm_grid_thiessen - time_start_all) print("Generating LSM Grid Rtree ...") rtree_idx = rtree.index.Index() # Populate R-tree index with bounds of ECMWF grid cells for lsm_grid_pos, lsm_grid_feature in enumerate(lsm_grid_feature_list): rtree_idx.insert(lsm_grid_pos, lsm_grid_feature['polygon'].bounds) time_end_lsm_grid_rtree = datetime.utcnow() print(time_end_lsm_grid_rtree - time_end_lsm_grid_thiessen) print("Retrieving catchment river id list ...") number_of_catchment_features = ogr_catchment_shapefile_lyr.GetFeatureCount() catchment_rivid_list = np.zeros(number_of_catchment_features, dtype=np.int32) for feature_idx, catchment_feature in enumerate(ogr_catchment_shapefile_lyr): catchment_rivid_list[feature_idx] = catchment_feature.GetField(river_id) print("Reading in RAPID connect file ...") rapid_connect_rivid_list = np.loadtxt(in_rapid_connect, delimiter=",", usecols=(0,), dtype=int) print("Find LSM grid cells that intersect with each catchment") print("and write out weight table ...") dummy_lat_index, dummy_lon_index = _get_lat_lon_indices(lsm_grid_lat, lsm_grid_lon, lsm_grid_feature_list[0]['lat'], lsm_grid_feature_list[0]['lon']) dummy_row_end = [0, dummy_lon_index, dummy_lat_index, 1, lsm_grid_feature_list[0]['lon'], lsm_grid_feature_list[0]['lat'] ] with open_csv(out_weight_table, 'w') as csvfile: connectwriter = csv.writer(csvfile) connectwriter.writerow(['rivid', 'area_sqm', 'lon_index', 'lat_index', 'npoints', 'lsm_grid_lon', 'lsm_grid_lat']) geographic_proj = Proj(init='EPSG:4326') #geographic osr_geographic_proj = osr.SpatialReference() osr_geographic_proj.ImportFromEPSG(4326) proj_transform = None if original_catchment_proj != geographic_proj: proj_transform = osr.CoordinateTransformation(ogr_catchment_shapefile_lyr_proj, osr_geographic_proj) for rapid_connect_rivid in rapid_connect_rivid_list: intersect_grid_info_list = [] try: catchment_pos = np.where(catchment_rivid_list==rapid_connect_rivid)[0][0] except IndexError: #if it is not in the catchment, add dummy row in its place connectwriter.writerow([rapid_connect_rivid] + dummy_row_end) continue pass get_catchment_feature = ogr_catchment_shapefile_lyr.GetFeature(catchment_pos) feat_geom = get_catchment_feature.GetGeometryRef() #make sure coordinates are geographic if proj_transform: feat_geom.Transform(proj_transform) catchment_polygon = shapely_loads(feat_geom.ExportToWkb()) for sub_lsm_grid_pos in rtree_idx.intersection(catchment_polygon.bounds): if catchment_polygon.intersects(lsm_grid_feature_list[sub_lsm_grid_pos]['polygon']): intersect_poly = catchment_polygon.intersection(lsm_grid_feature_list[sub_lsm_grid_pos]['polygon']) if not area_id: #attempt to calculate AREA poly_area = get_poly_area_geo(intersect_poly) else: poly_area = float(catchment_polygon.GetFeature(area_id))*intersect_poly.area/catchment_polygon.area index_lsm_grid_lat, index_lsm_grid_lon = _get_lat_lon_indices(lsm_grid_lat, lsm_grid_lon, lsm_grid_feature_list[sub_lsm_grid_pos]['lat'], lsm_grid_feature_list[sub_lsm_grid_pos]['lon']) intersect_grid_info_list.append({'rivid' : rapid_connect_rivid, 'area' : poly_area, 'lsm_grid_lat': lsm_grid_feature_list[sub_lsm_grid_pos]['lat'], 'lsm_grid_lon': lsm_grid_feature_list[sub_lsm_grid_pos]['lon'], 'index_lsm_grid_lon': index_lsm_grid_lon, 'index_lsm_grid_lat': index_lsm_grid_lat}) npoints = len(intersect_grid_info_list) #If no intersection found, add dummy row if(npoints <=0): connectwriter.writerow([rapid_connect_rivid] + dummy_row_end) for intersect_grid_info in intersect_grid_info_list: connectwriter.writerow([intersect_grid_info['rivid'], intersect_grid_info['area'], intersect_grid_info['index_lsm_grid_lon'], intersect_grid_info['index_lsm_grid_lat'], npoints, intersect_grid_info['lsm_grid_lon'], intersect_grid_info['lsm_grid_lat']]) time_end_all = datetime.utcnow() print(time_end_all - time_end_lsm_grid_rtree) print("TOTAL TIME: {0}".format(time_end_all - time_start_all))