def clip_rasters(folder_in, folder_out, aoi_in): """Read continental rasters one at a time, clip to AOI and save Parameters ---------- folder_in : str, Path Path to directory containing rasters. folder_out : str, Path Path to directory to save clipped rasters. aoi_in : str, Path Path to an AOI file (readable by Fiona) to use for clipping. """ if isinstance(aoi_in, gpd.GeoDataFrame): aoi = aoi_in else: aoi = gpd.read_file(aoi_in) coords = [json.loads(aoi.to_json())["features"][0]["geometry"]] for file_path in os.listdir(folder_in): if file_path.endswith(".tif"): print(f"Doing {file_path}") ntl_rd = rasterio.open(os.path.join(folder_in, file_path)) ntl, affine = mask(dataset=ntl_rd, shapes=coords, crop=True, nodata=0) if ntl.ndim == 3: ntl = ntl[0] save_raster(folder_out / file_path, ntl, affine)
def optimise( targets, costs, start, jupyter=False, animate=False, affine=None, animate_path=None, silent=False, ): """Run the Dijkstra algorithm for the supplied arrays. Parameters ---------- targets : numpy array 2D array of targets. costs : numpy array 2D array of costs. start : tuple Two-element tuple with row, col of starting point. jupyter : boolean, optional (default False) Whether the code is being run from a Jupyter Notebook. Returns ------- dist : numpy array 2D array with the distance (in cells) of each point from a 'found' on-grid point. Values of 0 imply that cell is part of an MV grid line. """ max_i = costs.shape[0] max_j = costs.shape[1] visited = np.zeros_like(targets, dtype=np.int8) dist = np.full_like(costs, np.nan, dtype=np.float32) # want to set this to dtype='int32, int32' # but then the if type(prev_loc) == tuple check will break # becuas it gets instantiated with tuples prev = np.full_like(costs, np.nan, dtype=object) dist[start] = 0 # dist, loc queue = [[0, start]] heapify(queue) def zero_and_heap_path(loc): """Zero the location's distance value and follow upstream doing same. Parameters ---------- loc : tuple row, col of current point. """ if not dist[loc] == 0: dist[loc] = 0 visited[loc] = 1 heappush(queue, [0, loc]) prev_loc = prev[loc] if type(prev_loc) == tuple: zero_and_heap_path(prev_loc) counter = 0 progress = 0 max_cells = targets.shape[0] * targets.shape[1] if jupyter: handle = display(Markdown(""), display_id=True) while len(queue): current = heappop(queue) current_loc = current[1] current_i = current_loc[0] current_j = current_loc[1] current_dist = dist[current_loc] for x in range(-1, 2): for y in range(-1, 2): next_i = current_i + x next_j = current_j + y next_loc = (next_i, next_j) # ensure we're within bounds if next_i < 0 or next_j < 0 or next_i >= max_i or next_j >= max_j: continue # ensure we're not looking at the same spot if next_loc == current_loc: continue # skip if we've already set dist to 0 if dist[next_loc] == 0: continue # if the location is connected if targets[next_loc]: prev[next_loc] = current_loc zero_and_heap_path(next_loc) # otherwise it's a normal queue cell else: dist_add = costs[next_loc] if x == 0 or y == 0: # if this cell is up/down/left/right dist_add *= 1 else: # or if it's diagonal dist_add *= sqrt(2) next_dist = current_dist + dist_add if visited[next_loc]: if next_dist + 0.4 < dist[next_loc]: dist[next_loc] = next_dist prev[next_loc] = current_loc heappush(queue, [next_dist, next_loc]) else: heappush(queue, [next_dist, next_loc]) visited[next_loc] = 1 dist[next_loc] = next_dist prev[next_loc] = current_loc counter += 1 progress_new = 100 * counter / max_cells if int(progress_new) > int(progress): progress = progress_new message = f"{progress:.2f} %" if jupyter: handle.update(message) elif not silent: print(message) if animate: i = int(progress) path = os.path.join(animate_path, f"arr{i:03d}.tif") save_raster(path, dist, affine) return dist