"""Cluster Average utility for wafer sensor values.""" from __future__ import annotations import math from pygui.backend.wafer.zwafer_models import Sensor def average_clusters(values: list[float], clusters: list[list[int]]) -> list[float]: """Return a new list of values where members of each cluster are replaced by their mean. NaN values are filtered out before computing the mean. If all values in a cluster are NaN, they remain NaN. """ result = list(values) for cluster in clusters: valid_vals = [] for idx in cluster: if idx < len(values): val = values[idx] if not math.isnan(val): valid_vals.append(val) if valid_vals: mean_val = sum(valid_vals) / len(valid_vals) for idx in cluster: if idx < len(result): result[idx] = mean_val return result def group_sensors_by_radius(sensors: list[Sensor], tolerance: float = 2.0) -> list[list[int]]: """Group sensor indices into clusters if their radial distances are within tolerance.""" # Compute radii for all sensors radii = [(i, math.hypot(s.x, s.y)) for i, s in enumerate(sensors)] # Filter out center sensors (r < 1.0) non_center = [item for item in radii if item[1] >= 1.0] if not non_center: return [] # Sort by radius non_center.sort(key=lambda x: x[1]) clusters: list[list[int]] = [] current_cluster: list[int] = [non_center[0][0]] last_r = non_center[0][1] for idx, r in non_center[1:]: if r - last_r <= tolerance: current_cluster.append(idx) else: if len(current_cluster) > 1: clusters.append(current_cluster) current_cluster = [idx] last_r = r if len(current_cluster) > 1: clusters.append(current_cluster) return clusters