def merge_files(f1, f2, out): print("Merging files...") try: fgc_shp = ogr.Open(f1) lyr1 = fgc_shp.GetLayer() fgc_shp2 = ogr.Open(f2) lyr2 = fgc_shp2.GetLayer() driver=ogr.GetDriverByName('ESRI Shapefile') ds=driver.CreateDataSource(out) merge_lyr = ds.CreateLayer('temp', lyr2.GetSpatialRef(), ogr.wkbMultiPolygon ) # diff_lyr = createFieldsFrom(lyr2, diff_lyr) print(" First file uninon..") union1 = ogr.Geometry(ogr.wkbMultiPolygon) for feat1 in lyr1: geom1 = feat1.GetGeometryRef() if geom1 != None: union1 = union1.Union(geom1) geom1 = None print(" Second file uninon..") union2 = ogr.Geometry(ogr.wkbMultiPolygon) for feat2 in lyr2: geom2 = feat2.GetGeometryRef() if geom2 != None: union2 = union2.Union(geom2) geom2 = None union1 = union1.Buffer(0) union2 = union2.Buffer(0) print(" Final uninon..") merge = union1.Union(union2) new_feat = ogr.Feature(merge_lyr.GetLayerDefn()) new_feat.SetGeometry(merge) merge_lyr.CreateFeature(new_feat) except: print("exception thrown!") traceback.print_exc() new_feat= None union1 = None union2 = None diff_lyr = None fgc_shp = None fgc_shp2 = None ds = None lyr1 = None lyr2 = None
def remove_biggest_polygon(f1, area, out): print("Removing biggest polygon") fgc_shp = ogr.Open(f1) lyr = fgc_shp.GetLayer() driver=ogr.GetDriverByName('ESRI Shapefile') ds=driver.CreateDataSource(out) holes_lyr = ds.CreateLayer('temp', lyr.GetSpatialRef(), ogr.wkbMultiPolygon ) max_area = 0.0 max_index = 0 for feature in lyr: geom = feature.GetGeometryRef() print(geom.GetGeometryCount()) for j in range(0,geom.GetGeometryCount() ): ring = geom.GetGeometryRef(j) area = ring.GetArea() print(area) if area> max_area: max_index = j max_area = area lyr =None fgc_shp = None # print("max= ", max_index) fgc_shp2 = ogr.Open(f1) lyr2 = fgc_shp2.GetLayer() for feature in lyr2: geom = feature.GetGeometryRef() for j in range(0,geom.GetGeometryCount()): ring = geom.GetGeometryRef(j) if j != max_index: new_feat = ogr.Feature(holes_lyr.GetLayerDefn()) new_feat.SetGeometry(ring.Buffer(0)) holes_lyr.CreateFeature(new_feat) new_feat = None # print(ring.GetArea()) holes_lyr = None ds=None lyr =None fgc_shp = None
def addBuffer(file,size, new_file): fgc_shp = ogr.Open(file) layer = fgc_shp.GetLayer() driver=ogr.GetDriverByName('ESRI Shapefile') ds=driver.CreateDataSource(new_file) out_lyr=ds.CreateLayer('temp', layer.GetSpatialRef(), ogr.wkbPolygon) out_lyr = createFieldsFrom(layer, out_lyr) for feature in layer: geom = feature.GetGeometryRef() if geom != None: new_feat = ogr.Feature(out_lyr.GetLayerDefn()) new_feat.SetFrom(feature) new_feat.SetGeometry(geom.Buffer(size)) out_lyr.CreateFeature(new_feat) # else: #out_lyr.CreateFeature(feature) new_feat = None geom = None out_lyr= None ds=None driver = None layer = None fgc_shp = None
def extent_polygon(file,out): fgc_shp = ogr.Open(file) lyr = fgc_shp.GetLayer() extent = lyr.GetExtent() ring = ogr.Geometry(ogr.wkbLinearRing) ring.AddPoint(extent[0], extent[2]) ring.AddPoint(extent[1], extent[2]) ring.AddPoint(extent[1], extent[3]) ring.AddPoint(extent[0], extent[3]) ring.AddPoint(extent[0], extent[2]) poly = ogr.Geometry(ogr.wkbPolygon) poly.AddGeometry(ring) driver=ogr.GetDriverByName('ESRI Shapefile') ds=driver.CreateDataSource(out) extent_lyr = ds.CreateLayer('temp', lyr.GetSpatialRef(), ogr.wkbMultiPolygon ) new_feat = ogr.Feature(extent_lyr.GetLayerDefn()) new_feat.SetGeometry(poly) extent_lyr.CreateFeature(new_feat) extent_lyr = None ds = None driver = None new_feat = None lyr = None fgc_shp = None
def get_interesecting_vdatum_regions(datafilepath): """ Find the vdatum regions that intersect the given data. """ dataset = gdal.Open(datafilepath) is_raster = dataset.RasterCount > 0 if is_raster: # get raster bounds crs = pyproj.CRS.from_wkt(dataset.GetProjectionRef()) transform = dataset.GetGeoTransform() pixelWidth = transform[1] pixelHeight = transform[5] cols = dataset.RasterXSize rows = dataset.RasterYSize x0 = transform[0] y1 = transform[3] x1 = x0+cols*pixelWidth y0 = y1-rows*pixelHeight if crs.is_projected: unproject = pyproj.Proj(proj='utm', zone = 19, ellps = 'WGS84') ul = unproject(x0,x1, inverse = True) ur = unproject(x1, y1, inverse = True) lr = unproject(x1, y0, inverse = True) ll = unproject(x0, y0, inverse = True) else: ul = (x0, y1) ur = (x1, y1) lr = (x1, y0) ll = (x0, y0) # build polygon from raster ring = ogr.Geometry(ogr.wkbLinearRing) ring.AddPoint(ul[0], ul[1]) ring.AddPoint(ur[0], ur[1]) ring.AddPoint(lr[0], lr[1]) ring.AddPoint(ll[0], ll[1]) ring.AddPoint(ul[0], ul[1]) dataGeometry = ogr.Geometry(ogr.wkbPolygon) dataGeometry.AddGeometry(ring) else: raise NotImplementedError('Not handling XYZ data yet') dataset = None # get all the regions represented by geometry files geom_list = get_vdatum_region_polygons() # see if the regions intersect with the provided geometries intersecting_regions = [] for region in geom_list: vector = ogr.Open(geom_list[region]) layer_count = vector.GetLayerCount() for m in range(layer_count): layer = vector.GetLayerByIndex(m) feature_count = layer.GetFeatureCount() for n in range(feature_count): feature = layer.GetFeature(n) feature_name = feature.GetField(0) if feature_name[:15] == 'valid-transform': valid_vdatum_poly = feature.GetGeometryRef() if dataGeometry.Intersect(valid_vdatum_poly): intersecting_regions.append(region) vector = None return intersecting_regions
def test_concav(file,out): points_by_id = get_points_from_geomety(file) fgc_shp = ogr.Open(file) lyr = fgc_shp.GetLayer() driver=ogr.GetDriverByName('ESRI Shapefile') ds1=driver.CreateDataSource(out) concave_lyr=ds1.CreateLayer('temp', lyr.GetSpatialRef(), ogr.wkbPolygon) concave_lyr = createFieldsFrom(lyr,concave_lyr) print("starting concave") ps = np.array([ ( points_by_id.iloc[xi,0] , np.array(points_by_id.iloc[xi,1]) ) for xi in range(0,points_by_id.shape[0]) ], dtype=object) #Processar em várias threads pool = multiprocessing.Pool(processes=multiprocessing.cpu_count()) res = pool.map( temp,ps ) print("End of concave calculations.") print("Saving to file") res = np.asarray(res,dtype=object) for i in range(0, res.shape[0]): try: fgc_id = res[i][0] hull = res[i][1] new_ring = ogr.Geometry(ogr.wkbLinearRing) hull = np.asarray(hull) for i in range(0, hull.shape[0]): new_ring.AddPoint(hull[i,0], hull[i,1]) poly = ogr.Geometry(ogr.wkbPolygon) poly.AddGeometry(new_ring) new_feat = ogr.Feature(concave_lyr.GetLayerDefn()) new_feat.SetField("ID_SEQ",fgc_id) new_feat.SetGeometry(poly) concave_lyr.CreateFeature(new_feat) new_feat = None except: print("exception thrown!") traceback.print_exc() break
def generate_geojson_features(self, shapefile_name): """ Generates and yields a series of meteocode geodata features, one for each feature in <self.filepath/self.filepath.stem/ shapefile_name>. Features are returned as ElasticSearch bulk API upsert actions, with documents in GeoJSON to match the ElasticSearch index mappings. :returns: Generator of ElasticSearch actions to upsert the forecast polygons for given shapefile in zip archive """ filepath = str( (self.filepath / self.filepath.stem / shapefile_name).resolve()) data = ogr.Open(r'/vsizip/{}'.format(filepath)) lyr = data.GetLayer() for feature in lyr: feature_json = feature.ExportToJson(as_object=True, options=['RFC7946=YES']) feature_json['properties']['version'] = self.version _id = feature_json['properties']['FEATURE_ID'] self.items.append(feature_json) action = { '_id': '{}'.format(_id), '_index': INDEX_NAME.format(self.zone.lower(), shapefile_name.split('_')[2]), '_op_type': 'update', 'doc': feature_json, 'doc_as_upsert': True } yield action
def get_points_from_geomety(file): print("Getting geometry points") fgc_shp = ogr.Open(file) lyr = fgc_shp.GetLayer() points_by_id = pd.DataFrame(data=[], columns=["id","points"]) for feature in lyr: # print("entrou") i_desc_fgc = feature.GetFieldIndex("ID_SEQ") fgc_id = feature.GetFieldAsInteger(i_desc_fgc) geom = feature.GetGeometryRef() for j in range(0,geom.GetGeometryCount() ): ring = geom.GetGeometryRef(j) if ring != None: #Se a faixa ainda nao foi vista adiciona ao dataframe if(points_by_id[points_by_id.iloc[:,0]==fgc_id].shape[0] == 0): points_by_id = points_by_id.append({'id' : fgc_id , 'points' :[] } , ignore_index=True) #Adicionar os pontos a lista de pontos da respetiva faixa # temp_points = points_by_id[points_by_id.iloc[:,0]==fgc_id].iloc[0,1] # print(" ",j," has", ring.GetPointCount(), " points" ) for i in range(0, ring.GetPointCount()): lon, lat, z = ring.GetPoint(i) points_by_id[points_by_id.iloc[:,0]==fgc_id].iloc[0,1].append((lon,lat)) # temp_points.append((lon,lat)) # else: # print(" ",j," is None" ) # points_by_id[points_by_id.iloc[:,0]==fgc_id].iloc[0,1] =temp_points fgc_shp = None lyr = None return points_by_id
def _tiger_to_tract(self, infile): """ Converts collection of Census Tiger files into a geopandas.GeoDataFrame of census tracts Modified from original at https://svn.osgeo.org/gdal/tags/1.4.3/gdal/pymod/samples/tigerpoly.py """ class Module(object): def __init__(mod): mod.lines = {} mod.poly_line_links = {} outfile = 'tracts.shp' # Open the datasource to operate on. ds = ogr.Open(infile, update=0) poly_layer = ds.GetLayerByName('Polygon') # Create output file for the composed polygons. nad83 = osr.SpatialReference() nad83.SetFromUserInput('NAD83') shp_driver = ogr.GetDriverByName('ESRI Shapefile') shp_driver.DeleteDataSource(outfile) shp_ds = shp_driver.CreateDataSource(outfile) shp_layer = shp_ds.CreateLayer( 'out', geom_type=ogr.wkbPolygon, srs=nad83) src_defn = poly_layer.GetLayerDefn() poly_field_count = src_defn.GetFieldCount() for fld_index in range(poly_field_count): src_fd = src_defn.GetFieldDefn(fld_index) fd = ogr.FieldDefn(src_fd.GetName(), src_fd.GetType()) fd.SetWidth(src_fd.GetWidth()) fd.SetPrecision(src_fd.GetPrecision()) shp_layer.CreateField(fd) # Read all features in the line layer, holding just the geometry in a hash # for fast lookup by TLID. line_layer = ds.GetLayerByName('CompleteChain') line_count = 0 modules_hash = {} feat = line_layer.GetNextFeature() geom_id_field = feat.GetFieldIndex('TLID') tile_ref_field = feat.GetFieldIndex('MODULE') while feat is not None: geom_id = feat.GetField(geom_id_field) tile_ref = feat.GetField(tile_ref_field) try: module = modules_hash[tile_ref] except: module = Module() modules_hash[tile_ref] = module module.lines[geom_id] = feat.GetGeometryRef().Clone() line_count = line_count + 1 feat.Destroy() feat = line_layer.GetNextFeature() # Read all polygon/chain links and build a hash keyed by POLY_ID listing # the chains (by TLID) attached to it. link_layer = ds.GetLayerByName('PolyChainLink') feat = link_layer.GetNextFeature() geom_id_field = feat.GetFieldIndex('TLID') tile_ref_field = feat.GetFieldIndex('MODULE') lpoly_field = feat.GetFieldIndex('POLYIDL') rpoly_field = feat.GetFieldIndex('POLYIDR') link_count = 0 while feat is not None: module = modules_hash[feat.GetField(tile_ref_field)] tlid = feat.GetField(geom_id_field) lpoly_id = feat.GetField(lpoly_field) rpoly_id = feat.GetField(rpoly_field) if lpoly_id == rpoly_id: feat.Destroy() feat = link_layer.GetNextFeature() continue try: module.poly_line_links[lpoly_id].append(tlid) except: module.poly_line_links[lpoly_id] = [tlid] try: module.poly_line_links[rpoly_id].append(tlid) except: module.poly_line_links[rpoly_id] = [tlid] link_count = link_count + 1 feat.Destroy() feat = link_layer.GetNextFeature() # Process all polygon features. feat = poly_layer.GetNextFeature() tile_ref_field = feat.GetFieldIndex('MODULE') polyid_field = feat.GetFieldIndex('POLYID') degenerate_count = 0 while feat is not None: module = modules_hash[feat.GetField(tile_ref_field)] polyid = feat.GetField(polyid_field) tlid_list = module.poly_line_links[polyid] link_coll = ogr.Geometry(type=ogr.wkbGeometryCollection) for tlid in tlid_list: geom = module.lines[tlid] link_coll.AddGeometry(geom) try: poly = ogr.BuildPolygonFromEdges(link_coll) if poly.GetGeometryRef(0).GetPointCount() < 4: degenerate_count = degenerate_count + 1 poly.Destroy() feat.Destroy() feat = poly_layer.GetNextFeature() continue feat2 = ogr.Feature(feature_def=shp_layer.GetLayerDefn()) for fld_index in range(poly_field_count): feat2.SetField(fld_index, feat.GetField(fld_index)) feat2.SetGeometryDirectly(poly) shp_layer.CreateFeature(feat2) feat2.Destroy() except: warn('BuildPolygonFromEdges failed.') feat.Destroy() feat = poly_layer.GetNextFeature() if degenerate_count: warn('Discarded %d degenerate polygons.' % degenerate_count) # Cleanup shp_ds.Destroy() shp_ds = None ds.Destroy() ds = None # build a fully-qualified fips code and dissolve on it to create tract geographies gdf = gpd.read_file(outfile) if "CTBNA90" in gdf.columns: gdf = gdf.rename(columns={"CTBNA90": 'TRACT', "BLK90": "BLOCK"}) gdf['STATE'] = gdf['STATE'].astype(str).str.rjust(2, "0") gdf['COUNTY'] = gdf['COUNTY'].astype(str).str.rjust(3, "0") gdf['TRACT'] = gdf['TRACT'].astype(str).str.rjust(6, "0") gdf['BLOCK'] = gdf['BLOCK'].astype(str).str.rjust(4, "0") gdf['fips'] = gdf.STATE + gdf.COUNTY + gdf.TRACT if self.geom == 'block': gdf['fips'] += gdf.BLOCK gdf = gdf.dropna(subset=['fips']) gdf.geometry = gdf.buffer(0) gdf = gdf.dissolve(by='fips') gdf.reset_index(inplace=True) shp_driver.DeleteDataSource(outfile) return gdf
def difference(f1, f2, out): try: print("Difference between:") print(" ",f1) print(" ",f2) fgc_shp = ogr.Open(f1) lyr1 = fgc_shp.GetLayer() fgc_shp2 = ogr.Open(f2) lyr2 = fgc_shp2.GetLayer() driver=ogr.GetDriverByName('ESRI Shapefile') ds=driver.CreateDataSource(out) diff_lyr = ds.CreateLayer('temp', lyr2.GetSpatialRef(), ogr.wkbMultiPolygon ) # diff_lyr = createFieldsFrom(lyr2, diff_lyr) union1 = ogr.Geometry(ogr.wkbMultiPolygon) for feat1 in lyr1: geom1 = feat1.GetGeometryRef() if geom1 != None: union1 = union1.Union(geom1) geom1 = None union2 = ogr.Geometry(ogr.wkbMultiPolygon) for feat2 in lyr2: geom2 = feat2.GetGeometryRef() if geom2 != None: union2 = union2.Union(geom2) geom2 = None union1 = union1.Buffer(0) union2 = union2.Buffer(0) print(union1.GetGeometryCount()) diff = union1.Difference(union2) new_feat = ogr.Feature(diff_lyr.GetLayerDefn()) new_feat.SetGeometry(diff) diff_lyr.CreateFeature(new_feat) # union1 = ogr.Geometry(ogr.wkbMultiPolygon) # for feat1 in lyr1: # geom1 = feat1.GetGeometryRef() # fgc_shp2 = ogr.Open(f2) # lyr2 = fgc_shp2.GetLayer() # for feat2 in lyr2: # geom2 = feat2.GetGeometryRef() # if geom1 != None and geom2 != None: ## if geom2.Intersects(geom1) or geom2.Within(geom1) or geom2.Overlaps(geom1) or geom2.Crosses(geom1): # diff = geom1.SymmetricDifference(geom2) # if diff != None: # union1.AddGeometry(diff) ## new_feat = ogr.Feature(diff_lyr.GetLayerDefn()) ## new_feat.SetGeometry(diff) ## diff_lyr.CreateFeature(new_feat) # # geom2 = None # new_feat = None # diff=None # # geom1 = None # new_feat = ogr.Feature(diff_lyr.GetLayerDefn()) # new_feat.SetGeometry(union1) # diff_lyr.CreateFeature(new_feat) except: print("exception thrown!") traceback.print_exc() new_feat= None union1 = None union2 = None diff_lyr = None fgc_shp = None fgc_shp2 = None ds = None lyr1 = None lyr2 = None
error_missing_str = "{0} geopackage must be specified either by {1} or --{0} argument" if not areas_path: logging.error(error_missing_str.format(AREAS_ARG_NAME, AREAS_ENV_VAR_NAME)) exit(1) if not local_features_path: logging.error( error_missing_str.format(LOCAL_FEATURES_ARG_NAME, LOCAL_FEATURES_ENV_VAR_NAME)) exit(1) else: # application expects the env var alone to provide this path, so ensure it has the correct value os.environ[LOCAL_FEATURES_ENV_VAR_NAME] = local_features_path datasource = ogr.Open(areas_path) if not datasource: logging.error("Could not open {0}. Exiting".format(areas_path)) exit(1) if datasource.GetLayerCount() != 1: logging.error("Expected 1 layer but instead found {0}. Exiting".format( datasource.GetLayerCount())) exit(1) def get_bounding_box(geom: ogr.Geometry) -> ogr.Geometry: return ogr.CreateGeometryFromWkt( f"POLYGON (({min_x} {min_y},{max_x} {min_y},{max_x} {max_y},{min_x} {max_y},{min_x} {min_y}))" )
def static_maps( source, # source folder containing clone destination, # destination folder inifile, # ini file with various settings dem_in, # path to digital elevation model (raster) rivshp, # path to river network (line vector) catchshp, # path to catchment polygon (polygon vector) gaugeshp=None, # path to gauge point (point vector) landuse=None, # path to land use / land cover (raster) soil=None, # path to soil type (raster) lai=None, # path to vegetation LAI (containing 12 GeoTiffs LAI00000.XXX.tif) other_maps=None, # bracketed [] comma-separated list of paths to other maps that should be reprojected logfilename="wtools_static_maps.log", # log file name verbose=True, clean=True, # Clean the .xml files from static maps folder when finished alltouch=False, # option to burn catchments "all touching".\nUseful when catchment-size is small compared to cellsize outlets=([], []), ): # parse other maps into an array if not other_maps == None: if type(other_maps) == str: print(other_maps) other_maps = ( other_maps.replace(" ", "").replace("[", "").replace("]", "").split(",") ) source = os.path.abspath(source) clone_tif = os.path.join(source, "mask.tif") clone_map = os.path.join(source, "mask.map") clone_shp = os.path.join(source, "mask.shp") clone_prj = os.path.join(source, "mask.prj") # open a logger, dependent on verbose print to screen or not logger, ch = wt.setlogger(logfilename, "WTOOLS", verbose) # create directories # TODO: check if workdir is still necessary, try to # keep in memory as much as possible # delete old files (when the source and destination folder are different) if np.logical_and(os.path.isdir(destination), destination is not source): shutil.rmtree(destination) if destination is not source: os.makedirs(destination) # Read mask if not (os.path.exists(clone_map)): logger.error( "Clone file {:s} not found. Please run create_grid first.".format(clone_map) ) sys.exit(1) else: # set clone pcr.setclone(clone_map) # get the extent from clone.tif xax, yax, clone, fill_value = wt.gdal_readmap(clone_tif, "GTiff") trans = wt.get_geotransform(clone_tif) extent = wt.get_extent(clone_tif) xmin, ymin, xmax, ymax = extent zeros = np.zeros(clone.shape) ones = pcr.numpy2pcr(pcr.Scalar, np.ones(clone.shape), -9999) # get the projection from clone.tif srs = wt.get_projection(clone_tif) unit_clone = srs.GetAttrValue("UNIT").lower() # READ CONFIG FILE # open config-file if inifile is None: config = configparser.ConfigParser() config.optionxform = str else: config = wt.OpenConf(inifile) # read settings """ read parameters """ minorder = wt.configget(config, "parameters", "riverorder_min", 3, datatype="int") try: percentiles_str = wt.configget( config, "parameters", "statisticmaps", "0, 100", datatype="str" ) percentiles_split = percentiles_str.replace(" ", "").split(",") percentiles = np.array(percentiles_split, dtype="float") except configparser.NoOptionError: percentiles = [0.0, 100.0] # read the parameters for generating a temporary very high resolution grid if unit_clone == "degree": cellsize_hr = wt.configget( config, "parameters", "highres_degree", 0.0005, datatype="float" ) elif (unit_clone == "metre") or (unit_clone == "meter"): cellsize_hr = wt.configget( config, "parameters", "highres_metre", 50, datatype="float" ) cols_hr = int((float(xmax) - float(xmin)) / cellsize_hr + 2) rows_hr = int((float(ymax) - float(ymin)) / cellsize_hr + 2) hr_trans = (float(xmin), cellsize_hr, float(0), float(ymax), 0, -cellsize_hr) clone_hr = os.path.join(destination, "clone_highres.tif") # make a highres clone as well! wt.CreateTif(clone_hr, rows_hr, cols_hr, hr_trans, srs, 0) # read staticmap locations dem_map = wt.configget(config, "staticmaps", "dem", "wflow_dem.map") gauges_map = wt.configget(config, "staticmaps", "gauges", "wflow_gauges.map") landuse_map = wt.configget(config, "staticmaps", "landuse", "wflow_landuse.map") river_map = wt.configget(config, "staticmaps", "river", "wflow_river.map") outlet_map = wt.configget(config, "staticmaps", "outlet", "wflow_outlet.map") soil_map = wt.configget(config, "staticmaps", "soil", "wflow_soil.map") streamorder_map = wt.configget( config, "staticmaps", "streamorder", "wflow_streamorder.map" ) subcatch_map = wt.configget(config, "staticmaps", "subcatch", "wflow_subcatch.map") # first add a missing value to dem_in ds = gdal.Open(dem_in, gdal.GA_Update) RasterBand = ds.GetRasterBand(1) fill_val = RasterBand.GetNoDataValue() if fill_val is None: RasterBand.SetNoDataValue(-9999) ds = None # reproject to clone map: see http://stackoverflow.com/questions/10454316/how-to-project-and-resample-a-grid-to-match-another-grid-with-gdal-python # resample DEM logger.info( "Resampling dem from {:s} to {:s}".format( os.path.abspath(dem_in), os.path.join(destination, dem_map) ) ) wt.gdal_warp( dem_in, clone_map, os.path.join(destination, dem_map), format="PCRaster", gdal_interp=gdalconst.GRA_Average, ) # retrieve amount of rows and columns from clone # TODO: make windowstats applicable to source/target with different projections. This does not work yet. # retrieve srs from DEM try: srs_dem = wt.get_projection(dem_in) except: logger.warning("No projection found in DEM, assuming WGS 1984 lat long") srs_dem = osr.SpatialReference() srs_dem.ImportFromEPSG(4326) clone2dem_transform = osr.CoordinateTransformation(srs, srs_dem) # if srs.ExportToProj4() == srs_dem.ExportToProj4(): wt.windowstats( dem_in, len(yax), len(xax), trans, srs, destination, percentiles, transform=clone2dem_transform, logger=logger, ) ## read catchment shape-file to create catchment map src = rasterio.open(clone_tif) shapefile = fiona.open(catchshp, "r") catchment_shapes = [feature["geometry"] for feature in shapefile] image = features.rasterize( catchment_shapes, out_shape=src.shape, all_touched=True, transform=src.transform ) catchment_domain = pcr.numpy2pcr(pcr.Ordinal, image.copy(), 0) ## read river shape-file and create burn layer shapefile = fiona.open(rivshp, "r") river_shapes = [feature["geometry"] for feature in shapefile] image = features.rasterize( river_shapes, out_shape=src.shape, all_touched=False, transform=src.transform ) rivers = pcr.numpy2pcr(pcr.Nominal, image.copy(), 0) riverdem = pcr.scalar(rivers) * pcr.readmap(os.path.join(destination, dem_map)) pcr.setglobaloption("lddin") riverldd = pcr.lddcreate(riverdem, 1e35, 1e35, 1e35, 1e35) riveroutlet = pcr.cover(pcr.ifthen(pcr.scalar(riverldd) == 5, pcr.scalar(1000)), 0) burn_layer = pcr.cover( ( pcr.scalar( pcr.ifthen(pcr.streamorder(riverldd) > 1, pcr.streamorder(riverldd)) ) - 1 ) * 1000 + riveroutlet, 0, ) outlets_x, outlets_y = outlets n_outlets = len(outlets_x) logger.info("Number of outlets: {}".format(n_outlets)) if n_outlets >= 1: outlets_map_numbered = points_to_map(pcr.scalar(0), outlets_x, outlets_y, 0.5) outlets_map = pcr.boolean(outlets_map_numbered) # snap outlets to closest river (max 1 cell closer to river) outlets_map = pcr.boolean( pcr.cover(snaptomap(pcr.ordinal(outlets_map), rivers), 0) ) ## create ldd per catchment logger.info("Calculating ldd") ldddem = pcr.scalar(clone_map) # per subcatchment, burn dem, then create modified dem that fits the ldd of the subcatchment # this ldd dem is merged over catchments, to create a global ldd that abides to the subcatchment boundaries for idx, shape in enumerate(catchment_shapes): logger.info( "Computing ldd for catchment " + str(idx + 1) + "/" + str(len(catchment_shapes)) ) image = features.rasterize( [shape], out_shape=src.shape, all_touched=True, transform=src.transform ) catchment = pcr.numpy2pcr(pcr.Scalar, image.copy(), 0) dem_burned_catchment = ( pcr.readmap(os.path.join(destination, dem_map)) * pcr.scalar(catchment_domain) * catchment ) - burn_layer ldddem = pcr.cover(ldddem, dem_burned_catchment) wflow_ldd = pcr.lddcreate(ldddem, 1e35, 1e35, 1e35, 1e35) if n_outlets >= 1: # set outlets to pit wflow_ldd = pcr.ifthenelse(outlets_map, pcr.ldd(5), wflow_ldd) wflow_ldd = pcr.lddrepair(wflow_ldd) pcr.report(wflow_ldd, os.path.join(destination, "wflow_ldd.map")) # compute stream order, identify river cells streamorder = pcr.ordinal(pcr.streamorder(wflow_ldd)) river = pcr.ifthen(streamorder >= pcr.ordinal(minorder), pcr.boolean(1)) # find the minimum value in the DEM and cover missing values with a river with this value. Effect is none!! so now left out! # mindem = int(np.min(pcr.pcr2numpy(pcr.ordinal(os.path.join(destination, dem_map)),9999999))) # dem_resample_map = pcr.cover(os.path.join(destination, dem_map), pcr.scalar(river)*0+mindem) # pcr.report(dem_resample_map, os.path.join(destination, dem_map)) pcr.report(streamorder, os.path.join(destination, streamorder_map)) pcr.report(river, os.path.join(destination, river_map)) # deal with your catchments if gaugeshp == None: logger.info("No gauges defined, using outlets instead") gauges = pcr.ordinal( pcr.uniqueid( pcr.boolean(pcr.ifthen(pcr.scalar(wflow_ldd) == 5, pcr.boolean(1))) ) ) pcr.report(gauges, os.path.join(destination, gauges_map)) # TODO: Add the gauge shape code from StaticMaps.py (line 454-489) # TODO: add river length map (see SticMaps.py, line 492-499) # since the products here (river length fraction) are not yet used # this is disabled for now, as it also takes a lot of computation time if False: # report river length # make a high resolution empty map dem_hr_file = os.path.join(destination, "dem_highres.tif") burn_hr_file = os.path.join(destination, "burn_highres.tif") demburn_hr_file = os.path.join(destination, "demburn_highres.map") riv_hr_file = os.path.join(destination, "riv_highres.map") wt.gdal_warp(dem_in, clone_hr, dem_hr_file) # wt.CreateTif(riv_hr, rows_hr, cols_hr, hr_trans, srs, 0) # open the shape layer ds = ogr.Open(rivshp) lyr = ds.GetLayer(0) wt.ogr_burn( lyr, clone_hr, -100, file_out=burn_hr_file, format="GTiff", gdal_type=gdal.GDT_Float32, fill_value=0, ) # read dem and burn values and add xax_hr, yax_hr, burn_hr, fill = wt.gdal_readmap(burn_hr_file, "GTiff") burn_hr[burn_hr == fill] = 0 xax_hr, yax_hr, dem_hr, fill = wt.gdal_readmap(dem_hr_file, "GTiff") dem_hr[dem_hr == fill] = np.nan demburn_hr = dem_hr + burn_hr demburn_hr[np.isnan(demburn_hr)] = -9999 wt.gdal_writemap( demburn_hr_file, "PCRaster", xax_hr, yax_hr, demburn_hr, -9999.0 ) pcr.setclone(demburn_hr_file) demburn_hr = pcr.readmap(demburn_hr_file) logger.info("Calculating ldd to determine river length") ldd_hr = pcr.lddcreate(demburn_hr, 1e35, 1e35, 1e35, 1e35) pcr.report(ldd_hr, os.path.join(destination, "ldd_hr.map")) pcr.setglobaloption("unitcell") riv_hr = pcr.scalar(pcr.streamorder(ldd_hr) >= minorder) * pcr.downstreamdist( ldd_hr ) pcr.report(riv_hr, riv_hr_file) pcr.setglobaloption("unittrue") pcr.setclone(clone_map) logger.info("Computing river length") wt.windowstats( riv_hr_file, len(yax), len(xax), trans, srs, destination, stat="fact", transform=False, logger=logger, ) # TODO: nothing happens with the river lengths yet. Need to decide how to use these # report outlet map pcr.report( pcr.ifthen(pcr.ordinal(wflow_ldd) == 5, pcr.ordinal(1)), os.path.join(destination, outlet_map), ) # report subcatchment map subcatchment = pcr.subcatchment(wflow_ldd, gauges) pcr.report(pcr.ordinal(subcatchment), os.path.join(destination, subcatch_map)) # Report land use map if landuse == None: logger.info( "No land use map used. Preparing {:s} with only ones.".format( os.path.join(destination, landuse_map) ) ) pcr.report(pcr.nominal(ones), os.path.join(destination, landuse_map)) else: logger.info( "Resampling land use from {:s} to {:s}".format( os.path.abspath(landuse), os.path.join(destination, os.path.abspath(landuse_map)), ) ) wt.gdal_warp( landuse, clone_map, os.path.join(destination, landuse_map), format="PCRaster", gdal_interp=gdalconst.GRA_Mode, gdal_type=gdalconst.GDT_Int32, ) # report soil map if soil == None: logger.info( "No soil map used. Preparing {:s} with only ones.".format( os.path.join(destination, soil_map) ) ) pcr.report(pcr.nominal(ones), os.path.join(destination, soil_map)) else: logger.info( "Resampling soil from {:s} to {:s}".format( os.path.abspath(soil), os.path.join(destination, os.path.abspath(soil_map)), ) ) wt.gdal_warp( soil, clone_map, os.path.join(destination, soil_map), format="PCRaster", gdal_interp=gdalconst.GRA_Mode, gdal_type=gdalconst.GDT_Int32, ) if lai == None: logger.info( "No vegetation LAI maps used. Preparing default maps {:s} with only ones.".format( os.path.join(destination, soil_map) ) ) pcr.report(pcr.nominal(ones), os.path.join(destination, soil_map)) else: dest_lai = os.path.join(destination, "clim") os.makedirs(dest_lai) for month in range(12): lai_in = os.path.join(lai, "LAI00000.{:03d}".format(month + 1)) lai_out = os.path.join(dest_lai, "LAI00000.{:03d}".format(month + 1)) logger.info( "Resampling vegetation LAI from {:s} to {:s}".format( os.path.abspath(lai_in), os.path.abspath(lai_out) ) ) wt.gdal_warp( lai_in, clone_map, lai_out, format="PCRaster", gdal_interp=gdalconst.GRA_Bilinear, gdal_type=gdalconst.GDT_Float32, ) # report soil map if other_maps == None: logger.info("No other maps used. Skipping other maps.") else: logger.info("Resampling list of other maps...") for map_file in other_maps: logger.info( "Resampling a map from {:s} to {:s}".format( os.path.abspath(map_file), os.path.join( destination, os.path.splitext(os.path.basename(map_file))[0] + ".map", ), ) ) wt.gdal_warp( map_file, clone_map, os.path.join( destination, os.path.splitext(os.path.basename(map_file))[0] + ".map", ), format="PCRaster", gdal_interp=gdalconst.GRA_Mode, gdal_type=gdalconst.GDT_Float32, ) if clean: wt.DeleteList(glob.glob(os.path.join(destination, "*.xml")), logger=logger) wt.DeleteList( glob.glob(os.path.join(destination, "clim", "*.xml")), logger=logger ) wt.DeleteList(glob.glob(os.path.join(destination, "*highres*")), logger=logger)