vyperdatum.utils.raster_utils ============================= .. py:module:: vyperdatum.utils.raster_utils Attributes ---------- .. autoapisummary:: vyperdatum.utils.raster_utils.logger Functions --------- .. autoapisummary:: vyperdatum.utils.raster_utils.band_stats vyperdatum.utils.raster_utils.raster_metadata vyperdatum.utils.raster_utils.add_overview vyperdatum.utils.raster_utils.add_rat vyperdatum.utils.raster_utils.set_nodatavalue vyperdatum.utils.raster_utils.unchanged_to_nodata vyperdatum.utils.raster_utils.raster_compress vyperdatum.utils.raster_utils.preserve_raster_size vyperdatum.utils.raster_utils.crs_to_code_auth vyperdatum.utils.raster_utils.push_pop_at_vshift vyperdatum.utils.raster_utils.raster_pre_transformation_checks vyperdatum.utils.raster_utils.raster_post_transformation_checks vyperdatum.utils.raster_utils.update_raster_wkt vyperdatum.utils.raster_utils.overwrite_with_original vyperdatum.utils.raster_utils.update_stats vyperdatum.utils.raster_utils.apply_nbs_bandnames vyperdatum.utils.raster_utils.add_uncertainty_band vyperdatum.utils.raster_utils.apply_nbs_band_standards vyperdatum.utils.raster_utils.create_cutline_from_grid vyperdatum.utils.raster_utils.create_cutline_file vyperdatum.utils.raster_utils.clip_raster_to_cutline vyperdatum.utils.raster_utils.add_vyper_tag Module Contents --------------- .. py:data:: logger .. py:function:: band_stats(band_array: numpy.ndarray) -> list Return a list containing the min, max, mean, and std of the band array. :param band_array: raster band array :type band_array: numpy.ndarray :param Returns: :param --------: :param list: min, max, mean, and std of the band array. .. py:function:: raster_metadata(raster_file: str, verbose: bool = False) -> dict .. py:function:: add_overview(raster_file: str, compression: str = '', embedded: bool = True, levels=None, resampling: str = 'AVERAGE') -> None Add overview bands to a raster file. :param raster_file: Absolute full path to the raster file. :type raster_file: str :param compression: The name of compression algorithm (e.g. ``DEFLATE``, ``LZW``). For float rasters compressed with DEFLATE or LZW, ``PREDICTOR=3`` is set so the overview pyramid compresses as efficiently as the original. Empty string leaves compression at GDAL defaults. :type compression: str :param embedded: If True the overviews are embedded in the file, otherwise stored externally as a .ovr sidecar. :type embedded: bool, default=True :param levels: Overview decimation factors. When None, an automatic pyramid is derived from the raster's longer side so the smallest level is no larger than approximately 256 pixels along its longer axis. For typical bathymetric tiles this produces seven to eight levels (e.g. 2, 4, 8, 16, 32, 64, 128). :type levels: list[int] | None, default=None :param resampling: Resampling algorithm. AVERAGE is appropriate for continuous data such as elevation; NEAREST is appropriate for categorical bands such as a contributor identifier raster. :type resampling: str, default="AVERAGE" .. py:function:: add_rat(raster: str) -> None Add Raster Attribute Table (RAT) to all bands of a raster file. :param raster_file: Absolute full path to the raster file. :type raster_file: str .. py:function:: set_nodatavalue(raster_file: str, band_nodatavalue: Union[list[tuple[int, float]], float]) -> None Change the NoDataValue of the raster file bands. :param raster_file: Absolute full path to the raster file. :type raster_file: str :param band_nodatavalue: A list of tuples: (band_index, NoDataValue). If a single float is passed, all bands will be affected. :type band_nodatavalue: Union[list[tuple[int, float]], float] .. py:function:: unchanged_to_nodata(src_raster_file: str, xform_raster_file: str, xform_band: int) -> None Compare the `xform_band` values of the `src_raster_file` and `xform_raster_file`. Change the values to NoDataValue if the transformed value is the same as the original value (indicating that the transformation has failed). Currentl, PROJ keep the source raster unchanged when fails to apply the transformation. The transformation fails when the source data is outside any of the underlying transformation grids. This function is meant to replace the failed transformation points with NoDataValue. :param src_raster_file: Absolute full path to the source raster file. :type src_raster_file: str :param xform_raster_file: Absolute full path to the transformed raster file. :type xform_raster_file: str :param xform_band: The reference band index that is used for comparison between the source and transformed file. :type xform_band: int .. py:function:: raster_compress(raster_file_path: str, output_file_path: str, format: str, compression: str) Compress raster file. :param raster_file_path: absolute path to the input raster file. :type raster_file_path: str :param output_file_path: absolute path to the compressed output raster file. :type output_file_path: str :param format: raster file format. :type format: str :param compression: compression algorithm. :type compression: str .. py:function:: preserve_raster_size(input_file: str, output_file: str) Resize the `output_file` raster dimensions to those of the input `input_file`. :param input_file: absolute path to the input raster file. :type input_file: str :param output_file: absolute path to the compressed output raster file. :type output_file: str .. py:function:: crs_to_code_auth(crs: pyproj.CRS) -> Optional[str] Return CRS string representation in form of code:authority :raises ValueError:: If either code or authority of the crs (or its sub_crs) can not be determined. :returns: crs string in form of code:authority :rtype: str .. py:function:: push_pop_at_vshift(pipe: str) -> str Sandwich the vgrid_shift operation with push/pop of the horizontal CRS components. :param pipe: :type pipe: proj pipeline string. .. py:function:: raster_pre_transformation_checks(source_meta: dict, source_crs: Union[pyproj.CRS, str]) Run a number of sanity checks on the source raster file, before transformation. Warns if a check fails. :param source_meta: Source raster metadata generated by `raster_metadata` function. :type source_meta: dict :returns: Returns True if all checks pass, otherwise False. :rtype: bool .. py:function:: raster_post_transformation_checks(source_meta: dict, target_meta: dict, target_crs: Union[pyproj.CRS, str], vertical_transform: bool) Run a number of sanity checks on the transformed raster file. Warns if a check fails. :param source_meta: Source raster metadata generated by `raster_metadata` function. :type source_meta: dict :param target_meta: Target raster metadata generated by `raster_metadata` function. :type target_meta: dict :param target_crs: The expected CRS object for the target raster file. :type target_crs: pyproj.crs.CRS or input used to create one :param vertical_transform: True if it's a vertical transformation, otherwise False. :type vertical_transform: bool :returns: Returns True if all checks pass, otherwise False. :rtype: bool .. py:function:: update_raster_wkt(input_file: str, wkt: str) -> None Assign a new WKT to a GeoTIFF in-place, or to a BAG by recreating the file. WARNING: This only *assigns* the SRS. If you're actually changing CRS (e.g., degrees->meters), you must reproject with gdal.Warp instead. :param input_file: Absolute path to the input raster file. :type input_file: str :param wkt: New WKT to update the raster file. :type wkt: str .. py:function:: overwrite_with_original(input_file: str, output_file: str) -> None Copy the non-elevation bands from ``input_file`` into ``output_file`` and mask their values to NoData wherever the output elevation is NoData. Same-CRS path ------------- When the input and output rasters have identical dimensions (the expected case for same-CRS transforms after the cutline-anchored two-pass warp), non-elevation bands are copied verbatim from the input. No resampling is performed. The uncertainty (or other non-elevation) band is masked so that values outside the valid elevation region become the elevation's NoData value. Different-CRS path ------------------ When dimensions differ, the function falls back to GDAL's resampling via ``buf_xsize`` / ``buf_ysize`` (the legacy behaviour). This path is not yet anchored to a target-CRS pixel grid and will produce a sub-pixel registration shift relative to the elevation band. A warning is logged so this case is visible in production. A correct different-CRS implementation requires re-warping each non-elevation band through the same coordinate pipeline as the elevation band and is deferred until that path is exercised. :param input_file: Path to the reference raster carrying the original non-elevation bands (typically the original input to ``transform_raster``). :type input_file: str :param output_file: Path to the transformed raster whose non-elevation bands are to be overwritten in place. :type output_file: str :raises ValueError: When the input or output cannot be opened, when no elevation band is identified in the input, or when the input has fewer than two bands (in which case nothing to do). .. py:function:: update_stats(input_file) Update statistics for the raster file. Parameters: input_file (str): Path to the raster file. .. py:function:: apply_nbs_bandnames(input_file) Apply NBS band names to the raster file. Sets the first band description to 'elevation' and the second band description to 'uncertainty' if the raster has more than one band. Parameters: input_file (str): Path to the raster file. .. py:function:: add_uncertainty_band(input_file: str) -> None .. py:function:: apply_nbs_band_standards(input_file: str) -> None Apply NBS band standards to the raster file. Sets the first band description to 'elevation' and the second band description to 'uncertainty' if the raster has more than one band. Adds uncertainty band if it does not exist, and updates statistics. Parameters: input_file (str): Path to the raster file. .. py:function:: create_cutline_from_grid(grid_path: str, output_cutline: str, input_extent=None, input_wkt: str = None) Create a cutline polygon from a GTG grid's valid (non-nodata) area, restricted to the vicinity of `input_extent` (bbox) when provided. This version supports rasters that span multiple subgrids by unioning all overlapping valid areas. .. py:function:: create_cutline_file(v_shift: bool, grid_files: list[str], cutline_path: str, input_metadata: dict) -> Optional[str] Create a cutline file from the provided grid files if vertical shift is applied. Otherwise, return None. TODO: what if more than one NWLD grids are involved? .. py:function:: clip_raster_to_cutline(input_path: str, cutline_path: str, output_path: str) -> Optional[str] Clip a raster against a cutline polygon while preserving the input's exact pixel grid. The clipped output is anchored to the input's geotransform: every output pixel boundary coincides with an input pixel boundary, so no sub-pixel shift is introduced by the clip step. The output extent is the smallest input-pixel-aligned rectangle that contains the cutline's envelope (intersected with the input's extent). The cutline polygon may be in a different CRS than the input raster; its envelope is reprojected on the fly into the input's CRS before snapping to the input's pixel grid. Pixels outside the cutline polygon are written as NoData. The output resolution, NoData value, metadata tags, and CRS match the input. :param input_path: Path to the input raster. :type input_path: str :param cutline_path: Path to the cutline vector dataset (e.g. GeoPackage). Polygon CRS may differ from the input raster's CRS. :type cutline_path: str :param output_path: Path where the clipped raster is written. :type output_path: str :returns: ``output_path`` on success, ``None`` on failure. :rtype: str or None .. py:function:: add_vyper_tag(raster_file: str, pipe: str, crs_to: pyproj.CRS, steps: list) -> None Add a Vyperdatum tag to the raster file to indicate it has been processed.