Source code for packing_defect.core.cluster

# packing_defect/core/cluster.py

import numpy as np


[docs] class DefectClustering:
[docs] @staticmethod def defect_size(matrices, nbins, bin_max, fname, prob=True): bins = np.linspace(0, bin_max, nbins) defects = [] for matrix in matrices: graph = DefectClustering._make_graph(matrix) visited = set() for node in graph: if node not in visited: cluster = DefectClustering._dfs(graph, node) visited |= cluster defects.append(len(cluster)) hist, _ = np.histogram(defects, bins) hist = hist.astype(np.float64) binp = 0.5 * (_[1:] + _[:-1]) if np.sum(hist) == 0: return if prob: hist /= np.sum(hist) np.savetxt(fname, np.column_stack((binp, hist)), fmt="%8.5f")
[docs] @staticmethod def cluster_sizes_from_mask(matrix: np.ndarray) -> list[int]: graph = DefectClustering._make_graph(matrix) visited, sizes = set(), [] for node in graph: if node not in visited: comp = DefectClustering._dfs(graph, node) visited |= comp sizes.append(len(comp)) return sizes
@staticmethod def _dfs(graph, start): visited, stack = set(), [start] while stack: node = stack.pop() if node not in visited: visited.add(node) stack.extend(graph[node] - visited) return visited @staticmethod def _make_graph(matrix): graph = {} rows, cols = matrix.shape for (x, y), val in np.ndenumerate(matrix): if val == 0: continue idx = x * cols + y neighbors = set() for dx in [-1, 0, 1]: for dy in [-1, 0, 1]: nx = (x + dx) % rows ny = (y + dy) % cols if matrix[nx, ny] == 1: nidx = nx * cols + ny neighbors.add(nidx) neighbors.discard(idx) graph[idx] = neighbors return graph