### example() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Create an example Raster. ```python @classmethod def example(cls) -> Self: """Create an example Raster.""" # Peaks dataset style example n = 256 x = np.linspace(-3, 3, n) y = np.linspace(-3, 3, n) x, y = np.meshgrid(x, y) z = np.exp(-(x**2) - y**2) * np.sin(3 * np.sqrt(x**2 + y**2)) arr = z.astype(np.float32) raster_meta = RasterMeta.example() return cls(arr=arr, raster_meta=raster_meta) ``` -------------------------------- ### example() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/meta Create an example RasterMeta object. ```python @classmethod def example(cls) -> Self: """Create an example RasterMeta object.""" return cls( crs=CRS.from_epsg(2193), transform=Affine.scale(2.0, 2.0), ) ``` -------------------------------- ### Raster Creation Examples Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Class methods for creating Raster objects, including an example dataset and creating a raster from another with a fill value. ```python @classmethod def example(cls) -> Self: """Create an example Raster.""" # Peaks dataset style example n = 256 x = np.linspace(-3, 3, n) y = np.linspace(-3, 3, n) x, y = np.meshgrid(x, y) z = np.exp(-(x**2) - y**2) * np.sin(3 * np.sqrt(x**2 + y**2)) arr = z.astype(np.float32) raster_meta = RasterMeta.example() return cls(arr=arr, raster_meta=raster_meta) ``` ```python @classmethod def full_like(cls, other: Raster, *, fill_value: float) -> Self: """Create a raster with the same metadata as another but filled with a constant. Args: other: The raster to copy metadata from. fill_value: The constant value to fill all cells with. Returns: A new raster with the same shape and metadata as `other`, but with all cells set to `fill_value`. """ arr = np.full(other.shape, fill_value, dtype=np.float32) return cls(arr=arr, raster_meta=other.raster_meta) ``` -------------------------------- ### replace_polygon examples Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Examples of how to use the replace_polygon method for single and multiple replacements. ```python >>> # Replace a single polygon >>> raster.replace_polygon(polygon1, value=np.nan) >>> # Replace multiple polygons >>> raster.replace_polygon({polygon1: 0, polygon2: 1}) ``` -------------------------------- ### sample Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example usage of the sample function, demonstrating how to handle NaN values and return raster values. ```python offset_xy_nan_idxs = xy_nan_idxs - np.arange(len(xy_nan_idxs)) raster_values = np.insert( raster_values, offset_xy_nan_idxs, np.nan, axis=0, ) if singleton: (raster_value,) = raster_values return raster_value return raster_values ``` -------------------------------- ### Raster Plotting Example Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster This code snippet demonstrates how to plot a raster, set axis limits, aspect ratio, and add a colorbar. It also shows how to use `rasterio.plot.show` for lower-level plotting. ```python x2, y2 = self.raster_meta.transform * ( # type: ignore[reportAssignmentType] max_x_unsuppressed + 1, max_y_unsuppressed + 1, ) xmin, xmax = sorted([x1, x2]) ymin, ymax = sorted([y1, y2]) model.arr[suppressed_mask] = np.nan img, *_ = model.rio_show(ax=ax, cmap=cmap, with_bounds=True, **kwargs) ax.set_xlim(xmin, xmax) ax.set_ylim(ymin, ymax) ax.set_aspect("equal", "box") ax.set_yticklabels([]) ax.set_xticklabels([]) ax.tick_params(left=False, bottom=False, top=False, right=False) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) fig = ax.get_figure() if fig is not None: fig.colorbar(img, label=cbar_label, cax=cax) return ax ``` ```python def rio_show(self, **kwargs: Any) -> list[AxesImage]: """Plot the raster using rasterio's built-in plotting function. This is useful for lower-level access to rasterio's plotting capabilities. Generally, the `plot()` method is preferred for most use cases. Args: **kwargs: Keyword arguments to pass to `rasterio.plot.show()`. This includes parameters like `alpha` for transparency, and `with_bounds` to control whether to plot in spatial coordinates or array index coordinates. """ with self.to_rasterio_dataset() as dataset: return rasterio.plot.show(dataset, **kwargs).get_images() ``` -------------------------------- ### infer Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/meta Automatically get recommended raster metadata (and shape) using data points. The cell size can be provided, or a heuristic will be used based on the spacing of the (x, y) points. Square cells are assumed unless a (cell_width, cell_height) pair is explicitly provided. ```python @classmethod def infer( cls, x: np.ndarray, y: np.ndarray, *, cell_size: tuple[float, float] | float | None = None, crs: CRS, ) -> tuple[Self, tuple[int, int]]: """Automatically get recommended raster metadata (and shape) using data points. The cell size can be provided, or a heuristic will be used based on the spacing of the (x, y) points. Square cells are assumed unless a `(cell_width, cell_height)` pair is explicitly provided. """ # Heuristic for cell size if not provided if cell_size is None: cell_size = infer_cell_size(x, y) cell_size = _ensure_pair(cell_size) shape = infer_shape(x, y, cell_size=cell_size) transform = infer_transform(x, y, cell_size=cell_size, crs=crs) raster_meta = cls( crs=crs, transform=transform, ) return raster_meta, shape ``` -------------------------------- ### Padding Operation Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example of the pad method, used to extend the raster by adding a constant fill value around the edges. ```python cell_width, cell_height = self.raster_meta.cell_size # Calculate number of cells to pad in each direction pad_cols = int(np.ceil(width / cell_width)) pad_rows = int(np.ceil(width / cell_height)) # Get current bounds xmin, ymin, xmax, ymax = self.bounds # Calculate new bounds with padding new_xmin = xmin - (pad_cols * cell_width) new_ymin = ymin - (pad_rows * cell_height) new_xmax = xmax + (pad_cols * cell_width) new_ymax = ymax + (pad_rows * cell_height) # Create padded array new_height = self.arr.shape[0] + 2 * pad_rows new_width = self.arr.shape[1] + 2 * pad_cols # Create new array filled with the padding value padded_arr = np.full((new_height, new_width), value, dtype=self.arr.dtype) ``` -------------------------------- ### resample method Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example of the resample method for changing raster resolution, including handling of cell size and resampling methods. ```python def resample( self, cell_size: tuple[float, float] | float, *, method: Literal["bilinear"] = "bilinear", ) -> Self: """Resample the raster data to a new resolution. If the new cell size is not an exact multiple of the current cell size, the overall raster bounds may increase slightly. The affine transform will keep the same shift, i.e. the top-left corner of the raster will remain in the same' coordinate location. A corollary is that the overall centre of the raster bounds will not necessary be the same as the original raster. Args: cell_size: The desired cell size for the resampled raster. This can be a single float for square cells, or a tuple of (cell_width, cell_height) for rectangular cells. method: The resampling method to use. Only 'bilinear' is supported. """ if method not in ("bilinear",): msg = f"Unsupported resampling method: {method}" raise NotImplementedError(msg) target_cell_width, target_cell_height = _ensure_pair(cell_size) source_cell_width, source_cell_height = self.raster_meta.cell_size x_factor = source_cell_width / target_cell_width y_factor = source_cell_height / target_cell_height cls = self.__class__ # Use the rasterio dataset with proper context management with self.to_rasterio_dataset() as dataset: # N.B. the new height and width may increase slightly. new_height = int(np.ceil(dataset.height * y_factor)) new_width = int(np.ceil(dataset.width * x_factor)) # Resample via rasterio (new_arr,) = dataset.read( out_shape=(dataset.count, new_height, new_width), resampling=Resampling.bilinear, ) # Create new RasterMeta with the exact requested cell size new_raster_meta = RasterMeta( transform=Affine( target_cell_width, dataset.transform.b, dataset.transform.c, dataset.transform.d, -target_cell_height, dataset.transform.f, ), crs=self.raster_meta.crs, ) return cls(arr=new_arr, raster_meta=new_raster_meta) ``` -------------------------------- ### Full sample method implementation Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster The complete implementation of the sample method, including type hints, docstrings, and logic for handling different input types and NaN values. ```python def sample( self, xy: Collection[tuple[float, float]] | Collection[Point] | ArrayLike | tuple[float, float] | Point | gpd.GeoDataFrame, *, na_action: Literal["raise", "ignore"] = "raise", ) -> NDArray | float: """Sample raster values at GeoSeries locations and return sampled values. Args: xy: A list of (x, y) coordinates, shapely Point objects, or a GeoDataFrame containing Point geometries to sample the raster at. na_action: Action to take when a NaN value is encountered in the input xy. Options are "raise" (raise an error) or "ignore" (replace with NaN). Returns: A list of sampled raster values for each geometry in the GeoSeries. """ # If this function is too slow, consider the optimizations detailed here: # https://rdrn.me/optimising-sampling/ import geopandas as gpd if isinstance(xy, gpd.GeoDataFrame): xy = _gdf_to_xy(xy, self.crs) singleton = False # Convert shapely Points to coordinate tuples if needed elif isinstance(xy, Point): xy = [(xy.x, xy.y)] singleton = True elif ( isinstance(xy, Collection) and len(xy) > 0 and isinstance(next(iter(xy)), Point) ): xy = [(point.x, point.y) for point in xy] # pyright: ignore[reportAttributeAccessIssue] singleton = False elif ( isinstance(xy, tuple) and len(xy) == 2 and isinstance(next(iter(xy)), (float, int)) ): xy = [xy] # pyright: ignore[reportAssignmentType] singleton = True else: singleton = False xy = np.asarray(xy, dtype=float) if len(xy) == 0: # Short-circuit return np.array([], dtype=float) # Create in-memory rasterio dataset from the incumbent Raster object with self.to_rasterio_dataset() as dataset: if dataset.count != 1: msg = "Only single band rasters are supported." raise NotImplementedError(msg) xy_arr = np.array(xy) # Determine the indexes of any x,y coordinates where either is NaN. # We will drop these indexes for the purposes of calling .sample, but # then we will add NaN values back in at the end, inserting NaN into the # results array. xy_is_nan = np.isnan(xy_arr).any(axis=1) xy_nan_idxs = list(np.atleast_1d(np.squeeze(np.nonzero(xy_is_nan)))) xy_arr = xy_arr[~xy_is_nan] if na_action == "raise" and len(xy_nan_idxs) > 0: nan_error_msg = "NaN value found in input coordinates" raise ValueError(nan_error_msg) # Sample the raster in-memory dataset (e.g. PGA values) at the coordinates samples = list( rasterio.sample.sample_gen( dataset, xy_arr, indexes=1, # Single band raster, N.B. rasterio is 1-indexed masked=True, ) ) # Convert the sampled values to a NumPy array and set masked values to NaN raster_values = np.array( [s.data[0] if not numpy.ma.getmask(s) else np.nan for s in samples] ).astype(float) if len(xy_nan_idxs) > 0: # Insert NaN values back into the results array # This is tricky because all the indexes get offset once we remove # elements. ``` -------------------------------- ### Create Rasterio Dataset Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Shows how to create a rasterio in-memory dataset from a Raster object, useful for interoperability with other geospatial libraries. ```python raster = Raster.example() with raster.to_rasterio_dataset() as dataset: ... ``` -------------------------------- ### unique() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the unique cell values in the raster, including NaN. ```python def unique(self) -> NDArray: """Get the unique cell values in the raster, including NaN. Returns: Array of unique values in the raster. """ return np.unique(self.arr.flatten()) ``` -------------------------------- ### sum() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the sum of all values in the raster, ignoring NaN values. ```python def sum(self) -> float: """Get the sum of all values in the raster, ignoring NaN values. Returns: The sum of all values in the raster. Returns zero if all values are NaN. """ with suppress_slice_warning(): return float(np.nansum(self.arr)) ``` -------------------------------- ### min() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the minimum value in the raster, ignoring NaN values. ```python def min(self) -> float: """Get the minimum value in the raster, ignoring NaN values. Returns: The minimum value in the raster. Returns NaN if all values are NaN. """ with suppress_slice_warning(): return float(np.nanmin(self.arr)) ``` -------------------------------- ### median() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the median value in the raster, ignoring NaN values. ```python def median(self) -> float: """Get the median value in the raster, ignoring NaN values. This is equivalent to quantile(0.5). Returns: The median value in the raster. Returns NaN if all values are NaN. """ with suppress_slice_warning(): return float(np.nanmedian(self.arr)) ``` -------------------------------- ### mean() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the mean value in the raster, ignoring NaN values. ```python def mean(self) -> float: """Get the mean value in the raster, ignoring NaN values. Returns: The mean value in the raster. Returns NaN if all values are NaN. """ with suppress_slice_warning(): return float(np.nanmean(self.arr)) ``` -------------------------------- ### RasterizationError Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/create Base exception for rasterization errors. ```python class RasterizationError(ValueError): """Base exception for rasterization errors.""" ``` -------------------------------- ### max() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the maximum value in the raster, ignoring NaN values. ```python def max(self) -> float: """Get the maximum value in the raster, ignoring NaN values. Returns: The maximum value in the raster. Returns NaN if all values are NaN. """ with suppress_slice_warning(): return float(np.nanmax(self.arr)) ``` -------------------------------- ### sample method signature (multiple points) Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Signature for the sample method when sampling at multiple points. ```python sample(xy: Collection[tuple[float, float]] | Collection[Point] | ArrayLike, *, na_action: Literal['raise', 'ignore'] = 'raise') -> NDArray ``` -------------------------------- ### get_xy() Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the x and y coordinates of the raster cell centres in meshgrid format. ```python def get_xy(self) -> tuple[NDArray[np.float64], NDArray[np.float64]]: """Get the x and y coordinates of the raster cell centres in meshgrid format. Returns the coordinates of the cell centres as two separate 2D arrays in meshgrid format, where each array has the same shape as the raster data array. Returns: A tuple of (x, y) coordinate arrays where: - x: 2D array of x-coordinates of cell centres - y: 2D array of y-coordinates of cell centres Both arrays have the same shape as the raster data array. """ coords = self.raster_meta.get_cell_centre_coords(self.arr.shape) return coords[:, :, 0], coords[:, :, 1] ``` -------------------------------- ### Replace values in the raster Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Demonstrates how to replace values in a raster, either a single value or multiple values using a dictionary. ```python raster.replace(to_replace=0, value=np.nan) raster.replace({0: np.nan, -999: np.nan}) ``` -------------------------------- ### quantile(q) Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Get the specified quantile value in the raster, ignoring NaN values. ```python def quantile(self, q: float) -> float: """Get the specified quantile value in the raster, ignoring NaN values. Args: q: Quantile to compute, must be between 0 and 1 inclusive. Returns: The quantile value. Returns NaN if all values are NaN. """ with suppress_slice_warning(): return float(np.nanquantile(self.arr, q)) ``` -------------------------------- ### sample method signature (single point) Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Signature for the sample method when sampling at a single point. ```python sample(xy: tuple[float, float] | Point, *, na_action: Literal['raise', 'ignore'] = 'raise') -> float ``` -------------------------------- ### raster_from_point_cloud Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/create Create a raster from a point cloud via interpolation. ```python def raster_from_point_cloud( x: ArrayLike, y: ArrayLike, z: ArrayLike, *, crs: CRS | str, cell_size: tuple[float, float] | float | None = None, ) -> Raster: """Create a raster from a point cloud via interpolation. Interpolation is only possible within the convex hull of the points. Outside of this, cells will be NaN-valued. Duplicate (x, y, z) triples are silently deduplicated. However, duplicate (x, y) points with different z values will raise an error. Args: x: X coordinates of points. y: Y coordinates of points. z: Values at each (x, y) point to assign the raster. crs: Coordinate reference system for the (x, y) coordinates. cell_size: Desired cell size for the raster. If None, a heuristic is used based on the spacing between (x, y) points. Returns: Raster containing the interpolated values. Raises: ValueError: If any (x, y) points have different z values, or if they are all collinear. """ cell_size = _ensure_pair(cell_size) if cell_size is not None else None crs = CRS.from_user_input(crs) x, y, z = _validate_xyz( np.asarray(x).ravel(), np.asarray(y).ravel(), np.asarray(z).ravel() ) raster_meta, shape = RasterMeta.infer(x, y, cell_size=cell_size, crs=crs) arr = interpn_kernel( points=np.column_stack((x, y)), values=z, xi=np.column_stack(_get_grid(raster_meta, shape=shape)), ).reshape(shape) # We only support float rasters for now; we should preserve the input dtype if # possible if z.dtype in (np.float16, np.float32, np.float64): arr = arr.astype(z.dtype) else: arr = arr.astype(np.float64) return Raster(arr=arr, raster_meta=raster_meta) ``` -------------------------------- ### Set Raster Origin Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Demonstrates how to set a new origin for a raster, normalizing it to the standard EPSG:4326 range. ```python raster = raster.set_origin(x=raster.origin[0] + 360) ``` -------------------------------- ### trim_zeros method Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example usage of the trim_zeros method to crop a raster by removing all-zero slices at the edges. ```python def trim_zeros(self) -> Self: """Crop the raster by trimming away all-zero slices at the edges. This effectively trims the raster to the smallest bounding box that contains all of the non-zero values. Note that this does not guarantee no zero values at all around the edges, only that there won't be entire edges which are all-zero. """ return self._trim_value(value_mask=(self.arr == 0), value_name="zero") ``` -------------------------------- ### Extrapolation Method Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example of the extrapolate method, which fills NaN values using the nearest non-NaN value. ```python if method not in ("nearest",): msg = f"Unsupported extrapolation method: {method}" raise NotImplementedError(msg) raster = self.model_copy() raster.arr = fillna_nearest_neighbours(arr=self.arr) return raster ``` -------------------------------- ### Sample raster values at coordinates Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster This code snippet demonstrates how to sample raster values at given x,y coordinates. It handles potential NaN values in input coordinates and masked values in the sampled data, returning NaN for masked values. It also supports returning a single value if `singleton` is True. ```python if len(xy) == 0: # Short-circuit return np.array([], dtype=float) # Create in-memory rasterio dataset from the incumbent Raster object with self.to_rasterio_dataset() as dataset: if dataset.count != 1: msg = "Only single band rasters are supported." raise NotImplementedError(msg) xy_arr = np.array(xy) # Determine the indexes of any x,y coordinates where either is NaN. # We will drop these indexes for the purposes of calling .sample, but # then we will add NaN values back in at the end, inserting NaN into the # results array. xy_is_nan = np.isnan(xy_arr).any(axis=1) xy_nan_idxs = list(np.atleast_1d(np.squeeze(np.nonzero(xy_is_nan)))) xy_arr = xy_arr[~xy_is_nan] if na_action == "raise" and len(xy_nan_idxs) > 0: nan_error_msg = "NaN value found in input coordinates" raise ValueError(nan_error_msg) # Sample the raster in-memory dataset (e.g. PGA values) at the coordinates samples = list( rasterio.sample.sample_gen( dataset, xy_arr, indexes=1, # Single band raster, N.B. rasterio is 1-indexed masked=True, ) ) # Convert the sampled values to a NumPy array and set masked values to NaN raster_values = np.array( [s.data[0] if not numpy.ma.getmask(s) else np.nan for s in samples] ).astype(float) if len(xy_nan_idxs) > 0: # Insert NaN values back into the results array # This is tricky because all the indexes get offset once we remove # elements. offset_xy_nan_idxs = xy_nan_idxs - np.arange(len(xy_nan_idxs)) raster_values = np.insert( raster_values, offset_xy_nan_idxs, np.nan, axis=0, ) if singleton: (raster_value,) = raster_values return raster_value return raster_values ``` -------------------------------- ### replace_polygon method - single replacement Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example of replacing values within a single polygon using the replace_polygon method. ```python raster.replace_polygon(polygon1, value=np.nan) ``` -------------------------------- ### Dilation Operation Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example of how the dilation operation works, including handling NaN values and preserving original metadata. ```python from skimage import morphology if not self.has_square_cells: msg = "Dilate currently only supports rasters with square cells." raise NotImplementedError(msg) cell_size = self.square_cell_size # Round up to nearest cell cell_radius = int(np.ceil(radius / cell_size)) # Calculate actual radius based on rounded cell count radius_m = cell_radius * cell_size # Store original NaN mask and shape original_nan_mask = np.isnan(self.arr) original_shape = self.arr.shape # Handle all-NaN case if np.all(original_nan_mask): return self.model_copy() # Pad the raster with non-consequential values to avoid edge effects fill_val = self.min() - 1.0 new_raster = self.model_copy() new_raster = new_raster.pad(width=radius_m, value=fill_val) # Replace NaNs with fill_val to avoid issues during dilation new_raster.arr[np.isnan(new_raster.arr)] = fill_val new_raster.arr = morphology.dilation( new_raster.arr, morphology.disk(cell_radius) ) # Crop back to original size using array slicing new_raster.arr = new_raster.arr[ cell_radius : cell_radius + original_shape[0], cell_radius : cell_radius + original_shape[1], ] # Restore original metadata new_raster = self.__class__(arr=new_raster.arr, meta=self.meta) # Restore original NaN values new_raster.arr[original_nan_mask] = np.nan return new_raster ``` -------------------------------- ### to_file(path, **kwargs) Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Write the raster to a file. ```python def to_file(self, path: Path | str, **kwargs: Any) -> None: """Write the raster to a file. Args: path: Path to output file. **kwargs: Additional keyword arguments to pass to `rasterio.open()`. If `nodata` is provided, NaN values in the raster will be replaced with the nodata value. """ from rastr.io_ import write_raster # noqa: PLC0415 return write_raster(self, path=path, **kwargs) ``` -------------------------------- ### full_like Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Create a raster with the same metadata as another but filled with a constant. ```python @classmethod def full_like(cls, other: Raster, *, fill_value: float) -> Self: """Create a raster with the same metadata as another but filled with a constant. Args: other: The raster to copy metadata from. fill_value: The constant value to fill all cells with. Returns: A new raster with the same shape and metadata as `other`, but with all cells set to `fill_value`. """ arr = np.full(other.shape, fill_value, dtype=np.float32) return cls(arr=arr, raster_meta=other.raster_meta) ``` -------------------------------- ### replace_polygon method - multiple replacements Source: https://rastr.readthedocs.io/en/stable/autoapi/rastr/raster Example of replacing values within multiple polygons using a dictionary with the replace_polygon method. ```python raster.replace_polygon({polygon1: 0, polygon2: 1}) ```