function extractHexaticOrder(I) % Input: % I = 2D image matrix (grayscale, double) % Output: % Plots original image + hexatic order + histogram %% 1) Detect dots (local maxima) I_smooth = imgaussfilt(I, 2); bw = imregionalmax(I_smooth); [y, x] = find(bw); if length(x) < 6 error('Too few detected dots (%d) for meaningful hexatic order.', length(x)); end %% 2) Compute hexatic order parameter psi6 % Delaunay triangulation to find neighbors tri = delaunay(x,y); N = length(x); neighbors = cell(N,1); for i = 1:size(tri,1) neighbors{tri(i,1)} = unique([neighbors{tri(i,1)} tri(i,2) tri(i,3)]); neighbors{tri(i,2)} = unique([neighbors{tri(i,2)} tri(i,1) tri(i,3)]); neighbors{tri(i,3)} = unique([neighbors{tri(i,3)} tri(i,1) tri(i,2)]); end psi6_vals = zeros(N,1); for j = 1:N nbrs = neighbors{j}; nbrs(nbrs == j) = []; if isempty(nbrs) psi6_vals(j) = 0; continue; end angles = atan2(y(nbrs)-y(j), x(nbrs)-x(j)); psi6_vals(j) = abs(mean(exp(1i*6*angles))); end psi6_global = mean(psi6_vals); %% 3) Plotting figure('Name','Hexatic Order Analysis','NumberTitle','off', 'Units','normalized', 'Position',[0.2 0.2 0.6 0.7]); t = tiledlayout(2,2, 'Padding','none', 'TileSpacing','compact'); % Top left: Original image with detected dots (square) ax1 = nexttile(1); imshow(I, []); hold on; scatter(x, y, 30, 'w', 'filled'); hold off; colormap(ax1, Helper.Colormaps.plasma()); % Example colormap for original image plot cbar1 = colorbar(ax1); cbar1.Label.Interpreter = 'latex'; xlabel(ax1, '$x$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14); ylabel(ax1, '$y$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14); title(ax1, '$|\Psi(x,y)|^2$', 'Interpreter', 'latex', 'FontSize', 14); axis(ax1, 'square'); % Top right: Histogram of local |psi6| (square) ax2 = nexttile(2); histogram(psi6_vals, 20, 'FaceColor', 'b'); xlabel(ax2, '$|\psi_6|$', 'Interpreter', 'latex', 'FontSize', 14); ylabel(ax2, 'Count'); title(ax2, 'Histogram of Local Hexatic Order'); xlim(ax2, [0 1]); grid(ax2, 'on'); axis(ax2, 'square'); % Bottom: Hexatic order magnitude on dots with bond orientation arrows (span 2 tiles) ax3 = nexttile([1 2]); scatter_handle = scatter(x, y, 50, psi6_vals, 'filled'); colormap(ax3, 'jet'); % Different colormap for hexatic order magnitude cbar3 = colorbar(ax3); cbar3.Label.String = '|$\psi_6$|'; cbar3.Label.Interpreter = 'latex'; caxis(ax3, [0 1]); axis(ax3, 'equal'); axis(ax3, 'tight'); title(ax3, sprintf('Local Hexatic Order |\\psi_6|, Global = %.3f', psi6_global)); hold(ax3, 'on'); for j = 1:N nbrs = neighbors{j}; nbrs(nbrs == j) = []; if isempty(nbrs) continue; end angles = atan2(y(nbrs)-y(j), x(nbrs)-x(j)); psi6_complex = mean(exp(1i*6*angles)); local_angle = angle(psi6_complex)/6; arrow_length = 5; quiver(ax3, x(j), y(j), arrow_length*cos(local_angle), arrow_length*sin(local_angle), ... 'k', 'MaxHeadSize', 2, 'AutoScale', 'off'); end hold(ax3, 'off'); end