Source code for polsartools.analysis.cluster_h_alpha_fp

import os
import numpy as np
from polsartools.utils.proc_utils import process_chunks_parallel
from polsartools.utils.utils import conv2d,time_it,read_rst

[docs] @time_it def cluster_h_alpha_fp(hFile,alphaFile , win=1, fmt="tif", cog=False, ovr = [2, 4, 8, 16], comp=False, max_workers=None,block_size=(512, 512), progress_callback=None, # for QGIS plugin ): """ Perform H-alpha clustering on given H-alpha files for full-pol SAR data. Examples -------- >>> # Basic usage with default parameters >>> cluster_h_alpha_fp("h_fp.tif", "alpha_fp.tif") >>> # Advanced usage with custom parameters >>> halpha_cluster_fp( ... hFile="h_fp.tif", ... alphaFile="alpha_fp.tif", ... win=5, ... fmt="tif", ... cog=True, ... block_size=(1024, 1024) ... ) Parameters ---------- hFile : str Path to the input Entropy file, H (polarimetric entropy). alphaFile : str Path to the input alpha file (average scattering angle). win : int, default=1 Size of the spatial averaging window. Larger windows reduce speckle noise but decrease spatial resolution. fmt : {'tif', 'bin'}, default='tif' Output file format: - 'tif': GeoTIFF format with georeferencing information - 'bin': Raw binary format cog : bool, default=False If True, creates a Cloud Optimized GeoTIFF (COG) with internal tiling and overviews for efficient web access. ovr : list[int], default=[2, 4, 8, 16] Overview levels for COG creation. Each number represents the decimation factor for that overview level. max_workers : int | None, default=None Maximum number of parallel processing workers. If None, uses CPU count - 1 workers. block_size : tuple[int, int], default=(512, 512) Size of processing blocks (rows, cols) for parallel computation. Larger blocks use more memory but may be more efficient. Returns ------- None Writes one output file to disk: - 'ha_cluster.tif' or 'ha_cluster.bin' - 'ha_cluster.png' """ input_filepaths = [hFile,alphaFile] infolder = os.path.dirname(hFile) output_filepaths = [] write_flag=True if fmt == "bin": output_filepaths.append(os.path.join(infolder, "ha_cluster.bin")) else: output_filepaths.append(os.path.join(infolder, "ha_cluster.tif")) def post_processing_task(input_filepaths, output_filepaths, **kwargs): zones = read_rst(output_filepaths[0]).astype(np.float32) zones[zones==0]=np.nan import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap, BoundaryNorm # Define colors for Z0-Z9 colors = [ (0, 0, 0, 0), # Index 0 transparent (RGBA) '#fe9394', # Z1 '#6aff68', # Z2 '#000000', # Z3 '#ff5151', # Z4 '#53fe4e', # Z5 '#5052fe', # Z6 '#8B0000', # Z7 '#0a9700', # Z8 '#000399' # Z9 ] # Create colormap including index 0 zone_cmap = ListedColormap(colors) plt.figure() im = plt.imshow(zones, cmap=zone_cmap, vmin=0, vmax=10) cbar = plt.colorbar(im, ticks=np.arange(1.5, 10, 1)) cbar.ax.set_yticklabels([f'Z{i}' for i in range(1, 10)]) cbar.outline.set_visible(False) plt.title(r"H-$\overline{\alpha}$ clusters") plt.axis('off') plt.tight_layout() plt.savefig(os.path.join(infolder, "ha_cluster.png"), bbox_inches='tight',dpi=300,transparent=True) plt.show() process_chunks_parallel(input_filepaths, list(output_filepaths), window_size=win, write_flag=write_flag, processing_func=process_chunk_hacfp,block_size=block_size, max_workers=max_workers, num_outputs=len(output_filepaths), cog=cog,ovr=ovr, comp=comp,post_proc=post_processing_task, progress_callback=progress_callback )
def process_chunk_hacfp(chunks, window_size,input_filepaths,*args): h = np.array(chunks[0]) alpha = np.array(chunks[1]) if window_size>1: kernel = np.ones((window_size,window_size),np.float32)/(window_size*window_size) h = conv2d(h,kernel) alpha = conv2d(alpha,kernel) zones = np.zeros_like(h, dtype=int) # Z1–Z3: h ∈ [0.9, 1.0] zones[(h >= 0.9) & (alpha >= 60)] = 1 # Z1 zones[(h >= 0.9) & (alpha >= 40) & (alpha < 60)] = 2 # Z2 zones[(h >= 0.9) & (alpha < 40)] = 3 # Z3 # Z4–Z6: h ∈ [0.5, 0.9) zones[(h >= 0.5) & (h < 0.9) & (alpha >= 50)] = 4 # Z4 zones[(h >= 0.5) & (h < 0.9) & (alpha >= 40) & (alpha < 50)] = 5 # Z5 zones[(h >= 0.5) & (h < 0.9) & (alpha < 40)] = 6 # Z6 # Z7–Z9: h < 0.5 zones[(h < 0.5) & (alpha >= 47.5)] = 7 # Z7 zones[(h < 0.5) & (alpha >= 42.5) & (alpha < 47.5)] = 8 # Z8 zones[(h < 0.5) & (alpha < 42.5)] = 9 # Z9 return zones.astype(np.uint8)