Skip to content

Utils

This module provides shared utility functions for raster operations.

Functions include path resolution for ENVI files, band extraction, and other common tasks.

compute_statistics(pixel_array)

Computes core summary statistics for a 1-dimensional numeric array utilizing a JIT-compiled pipeline.

Parameters:

Name Type Description Default
pixel_array ndarray

A flat, contiguous array of isolated pixel intensity values cast to float64.

required

Returns:

Type Description
Tuple[float, float, float, float, float]

Tuple[float, float, float, float, float]: A structured sequence containing the median, mean, standard deviation, minimum, and maximum values respectively.

Source code in src/phytospatial/raster/utils.py
@njit(cache=True, fastmath=True)
def compute_statistics(
    pixel_array: np.ndarray
    ) -> Tuple[float, float, float, float, float]:
    """
    Computes core summary statistics for a 1-dimensional numeric array utilizing a JIT-compiled pipeline.

    Args:
        pixel_array (np.ndarray): A flat, contiguous array of isolated pixel intensity values cast to float64.

    Returns:
        Tuple[float, float, float, float, float]: A structured sequence containing the median, mean, 
                                                  standard deviation, minimum, and maximum values respectively.
    """
    med = np.median(pixel_array)
    mean = np.mean(pixel_array)
    sd = np.std(pixel_array)
    min_v = np.min(pixel_array)
    max_v = np.max(pixel_array)
    return med, mean, sd, min_v, max_v

extract_band_indices(src, bands)

Normalize band selection to a list of 1-based indices.

Source code in src/phytospatial/raster/utils.py
def extract_band_indices(
    src: rasterio.DatasetReader, 
    bands: Optional[Union[int, List[int]]]
    ) -> List[int]:
    """
    Normalize band selection to a list of 1-based indices.
    """
    if bands is None:
        return list(src.indexes)
    elif isinstance(bands, int):
        return [bands]
    return list(bands)

extract_band_names(src, indices)

Extract descriptions/names for specific bands.

Source code in src/phytospatial/raster/utils.py
def extract_band_names(
    src: rasterio.DatasetReader, 
    indices: List[int]
    ) -> Dict[str, int]:
    """
    Extract descriptions/names for specific bands.
    """
    band_names = {}
    for i, idx in enumerate(indices):
        if 0 <= (idx - 1) < len(src.descriptions):
            desc = src.descriptions[idx - 1]
            if desc:
                band_names[desc] = i + 1
    return band_names

map_wavelengths(parsed_wavelengths, required_wavelengths, max_tolerance=20.0)

Matches required formula variables to actual 1-based band indices based on wavelength proximity.

Source code in src/phytospatial/raster/utils.py
def map_wavelengths(
    parsed_wavelengths: Dict[float, int], 
    required_wavelengths: Dict[str, float],
    max_tolerance: float = 20.0
    ) -> Dict[str, int]:
    """
    Matches required formula variables to actual 1-based band indices based on wavelength proximity.
    """
    if not parsed_wavelengths:
        raise ValueError("No parsable wavelengths found in file metadata or descriptions.")

    available_wvl = np.array(list(parsed_wavelengths.keys()))
    mapping = {}

    for var_name, target_wvl in required_wavelengths.items():
        idx = np.argmin(np.abs(available_wvl - target_wvl))
        matched_wvl = available_wvl[idx]

        if abs(matched_wvl - target_wvl) > max_tolerance:
            raise ValueError(f"No band found within {max_tolerance}nm of {target_wvl}nm for '{var_name}'")

        mapping[var_name] = parsed_wavelengths[matched_wvl]

    return mapping

resolve_envi_path(path)

Resolve ENVI header/binary file confusion. If 'image.hdr' is passed, redirects to 'image' (binary).

Source code in src/phytospatial/raster/utils.py
def resolve_envi_path(
        path: Union[str, Path]
        ) -> Path:
    """
    Resolve ENVI header/binary file confusion.
    If 'image.hdr' is passed, redirects to 'image' (binary).
    """
    path = Path(path)
    if path.suffix.lower() == '.hdr':
        binary_path = path.with_suffix('')
        if binary_path.exists():
            return binary_path
    return path