Source code for polsartools.analysis.halpha_cluster_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 halpha_cluster_fp(hFile,alphaFile , window_size=1, outType="tif", cog_flag=False, cog_overviews = [2, 4, 8, 16], write_flag=True, 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 >>> halpha_cluster_fp("h_fp.tif", "alpha_fp.tif") >>> # Advanced usage with custom parameters >>> halpha_cluster_fp( ... hFile="h_fp.tif", ... alphaFile="alpha_fp.tif", ... window_size=5, ... outType="tif", ... cog_flag=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). window_size : int, default=1 Size of the spatial averaging window. Larger windows reduce speckle noise but decrease spatial resolution. outType : {'tif', 'bin'}, default='tif' Output file format: - 'tif': GeoTIFF format with georeferencing information - 'bin': Raw binary format cog_flag : bool, default=False If True, creates a Cloud Optimized GeoTIFF (COG) with internal tiling and overviews for efficient web access. cog_overviews : list[int], default=[2, 4, 8, 16] Overview levels for COG creation. Each number represents the decimation factor for that overview level. write_flag : bool, default=True If True, writes results to disk. If False, only processes data in memory. 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 = [] if outType == "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(*args, **kwargs): zones = read_rst(output_filepaths[0]) import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap # Define colors for Z1–Z9 (index 0 is unused) colors = [ '#000000', # Index 0 (unused) '#00FF00', # Z1 - bright green (strong volume) '#ADFF2F', # Z2 - yellow-green (moderate volume) '#FF00FF', # Z3 - megenta (low volume/helicity) '#228B22', # Z4 - forest green (dense volume) '#FFD700', # Z5 - gold (mixed vegetation-ground) '#4682B4', # Z6 - steel blue (rough surface) '#FF0000', # Z7 - red (strong double-bounce) '#D2691E', # Z8 - tan/brown (mixed corner-ground) '#0000ff' # Z9 - light gray (flat surface / Bragg) ] # Create custom colormap zone_cmap = ListedColormap(colors[1:]) # Skip index 0 # Display zone map plt.figure() im = plt.imshow(zones, cmap=zone_cmap, vmin=1, 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)]) 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) plt.show() process_chunks_parallel(input_filepaths, list(output_filepaths), window_size=window_size, write_flag=write_flag, processing_func=process_chunk_hacfp,block_size=block_size, max_workers=max_workers, num_outputs=len(output_filepaths), cog_flag=cog_flag, cog_overviews=cog_overviews,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)