%% Evolve across a second-order-like transition
clear; clc;

N_params     = 50;
N_reps       = 50;
alpha_values = linspace(0, 45, N_params);
all_data     = cell(1, N_params);

% Transition control
alpha_start       = 5;     % where sigma starts changing
alpha_widen_end   = 15;    % when sigma finishes first change
alpha_shift_start = 15;    % when mean starts shifting
alpha_end         = 40;    % when mean finishes shifting and sigma narrows

mu_start    = 1.2;   % high initial mean
mu_end      = 0.2;   % low final mean

sigma_start = 0.25;  % wide std at start
sigma_mid   = 0.15;  % mid-range std in middle
sigma_end   = 0.07;  % narrow std at end

max_skew    = 5;     % peak skew strength

for i = 1:N_params
    alpha = alpha_values(i);

    % === Sigma evolution (variance large -> small) ===
    if alpha < alpha_start
        sigma = sigma_start;  % wide at start
    elseif alpha < alpha_widen_end
        % Smooth transition from wide to mid
        t_sigma = (alpha - alpha_start) / (alpha_widen_end - alpha_start);
        sigma = sigma_start * (1 - t_sigma) + sigma_mid * t_sigma;
    elseif alpha < alpha_end
        % Smooth transition from mid to narrow
        t_sigma = (alpha - alpha_widen_end) / (alpha_end - alpha_widen_end);
        sigma = sigma_mid * (1 - t_sigma) + sigma_end * t_sigma;
    else
        sigma = sigma_end;  % narrow at end
    end

    % === Mean evolution ===
    if alpha < alpha_shift_start
        mu = mu_start;  % fixed at high initially
    elseif alpha <= alpha_end
        % Smooth cosine shift
        t_mu = (alpha - alpha_shift_start) / (alpha_end - alpha_shift_start);
        smooth_t_mu = (1 - cos(pi * t_mu)) / 2;
        mu = mu_start * (1 - smooth_t_mu) + mu_end * smooth_t_mu;
    else
        mu = mu_end;
    end

    % === Skew evolution ===
    if alpha < alpha_end
        t_skew = (alpha - alpha_start) / (alpha_end - alpha_start);
        skew_strength = max_skew * (1 - t_skew);  % fade out
    else
        skew_strength = 0;
    end

    % Generate data
    if abs(skew_strength) < 1e-2
        data = normrnd(mu, sigma, [N_reps, 1]);
    else
        data = skewnormrnd(mu, sigma, skew_strength, N_reps);
    end

    all_data{i} = data;

    % Cumulants
    kappa = computeCumulants(data, 6);
    mean_vals(i)   = kappa(1);
    var_vals(i)    = kappa(2);
    skew_vals(i)   = kappa(3);
    kappa4_vals(i) = kappa(4);
    kappa5_vals(i) = kappa(5);
    kappa6_vals(i) = kappa(6);
end

%% Evolve across a first-order-like transition
% First-order-like distribution evolution with significant bimodality
clear; clc;

N_params       = 50;
N_reps         = 50;
alpha_values   = linspace(0, 45, N_params);

all_data       = cell(1, N_params);

% Define transition regions
skewed_start       = 10;
bimodal_start      = 20;
bimodal_end        = 35;
final_narrow_start = 40;

% Peak positions and widths
mu_high      = 1.2;   % Initial metastable peak
mu_low       = 0.2;   % Final stable peak
mu_new_peak  = 0.8;   % New peak appears slightly lower
sigma_initial = 0.08;

for i = 1:N_params
    alpha = alpha_values(i);

    if alpha < skewed_start
        % Region I: Narrow unimodal at high mean
        data = normrnd(mu_high, sigma_initial, [N_reps, 1]);

    elseif alpha < bimodal_start
        % Region II: Slightly skewed
        t_skew = (alpha - skewed_start) / (bimodal_start - skewed_start);
        mu     = mu_high - 0.15 * t_skew;
        sigma  = sigma_initial + 0.02 * t_skew;
        skew_strength = 3 * t_skew;
        data   = skewnormrnd(mu, sigma, skew_strength, N_reps);

    elseif alpha < bimodal_end
        % Region III: Bimodal with fixed or slowly drifting peak positions
        t = (alpha - bimodal_start) / (bimodal_end - bimodal_start);  % t in [0, 1]

        % Increased separation between peaks
        drift_amount = 0.3;  % larger = more drift toward final mean
        sep_offset   = 0.25; % larger = more initial separation between peaks

        % Peaks start separated and move toward mu_low
        mu1 = mu_high * (1 - t)^drift_amount + mu_low * (1 - (1 - t)^drift_amount);        % Right peak drifts to left
        mu2 = (mu_new_peak - sep_offset) * (1 - t)^drift_amount + mu_low * (1 - (1 - t)^drift_amount);  % Left peak moves slightly

        sigma1 = sigma_initial + 0.02 * (1 - abs(0.5 - t) * 2);
        sigma2 = sigma1;

        % Weight shift: right peak dies out, left peak grows
        w2 = 0.5 + 0.5 * t;  % left peak grows: 0.5 → 1
        w1 = 1 - w2;         % right peak fades: 0.5 → 0

        N1 = round(N_reps * w1);
        N2 = N_reps - N1;

        mode1 = normrnd(mu1, sigma1, [N1, 1]);
        mode2 = normrnd(mu2, sigma2, [N2, 1]);

        data = [mode1; mode2];
        data = data(randperm(length(data)));

    else
        % Region IV: Final stable low-mean Gaussian
        data = normrnd(mu_low, sigma_initial, [N_reps, 1]);
    end

    % Store data and compute cumulants
    all_data{i}    = data;
    kappa          = computeCumulants(data, 6);
    mean_vals(i)   = kappa(1);
    var_vals(i)    = kappa(2);
    skew_vals(i)   = kappa(3);
    kappa4_vals(i) = kappa(4);
    kappa5_vals(i) = kappa(5);
    kappa6_vals(i) = kappa(6);
end

%% === Compute 2D PDF heatmap: f(x, alpha) ===
x_grid = linspace(0.0, 1.8, 200);  % max[g²] values on y-axis
pdf_matrix = zeros(numel(x_grid), N_params);  % Now: rows = y, columns = alpha

for i = 1:N_params
    data = all_data{i};
    f = ksdensity(data, x_grid, 'Bandwidth', 0.025);
    pdf_matrix(:, i) = f;  % Transpose for y-axis to be vertical
end

% === Plot PDF vs. alpha heatmap ===
figure(2); clf;
set(gcf, 'Color', 'w', 'Position',[100 100 950 750])

imagesc(alpha_values, x_grid, pdf_matrix);
set(gca, 'YDir', 'normal');  % Flip y-axis to normal orientation
xlabel('$\alpha$ (degrees)', 'Interpreter', 'latex', 'FontSize', 14);
ylabel('$\mathrm{max}[g^{(2)}]$', 'Interpreter', 'latex', 'FontSize', 14);
title('Evolving PDF of $\mathrm{max}[g^{(2)}]$', ...
      'Interpreter', 'latex', 'FontSize', 16);

colormap(Colormaps.coolwarm());  % More aesthetic than default
colorbar;
c = colorbar;
ylabel(c, 'PDF', 'FontSize', 14, 'Interpreter', 'latex');
set(gca, 'FontSize', 14);

%% Animate evolving distribution and cumulant value
figure(1); clf;
set(gcf, 'Color', 'w', 'Position',[100 100 1300 750])

for i = 1:N_params
    clf;

    % PDF
    subplot(1,2,1); cla; hold on;
    data = all_data{i};
    
    % Plot histogram with normalized PDF
    histogram(data, 'Normalization', 'pdf', 'BinWidth', 0.03, ...
        'FaceColor', [0.3 0.5 0.8], 'EdgeColor', 'k', 'FaceAlpha', 0.6);
    
    title(sprintf('Histogram at $\\alpha = %.1f^\\circ$', alpha_values(i)), ...
        'Interpreter', 'latex', 'FontSize', 16);
    xlabel('$\mathrm{max}[g^{(2)}]$', 'Interpreter', 'latex', 'FontSize', 14);
    ylabel('PDF', 'FontSize', 14);
    set(gca, 'FontSize', 12); grid on;
    xlim([0.0, 2.0]);


    % Cumulant evolution
    subplot(1,2,2); hold on;
    plot(alpha_values(1:i), kappa4_vals(1:i), 'bo-', 'LineWidth', 2);
    title('Binder Cumulant Tracking', 'Interpreter', 'latex', 'FontSize', 16);
    xlabel('$\alpha$ (degrees)', 'Interpreter', 'latex', 'FontSize', 14);
    ylabel('$\kappa_4$', 'Interpreter', 'latex', 'FontSize', 14);
    xlim([0, 45]); grid on;
    set(gca, 'FontSize', 12);

    pause(0.3);
end

%% === Plotting ===
figure(1)
set(gcf, 'Color', 'w', 'Position', [100 100 950 750])
t = tiledlayout(2, 2, 'TileSpacing', 'compact', 'Padding', 'compact');

scan_vals = alpha_values;  % your parameter sweep values

% Define font style for consistency
axis_fontsize  = 14;
label_fontsize = 16;
title_fontsize = 16;

% 1. Mean with error bars (if you have error data, else just plot)
% If no error, replace errorbar with plot or omit error data
% For now, no error bars assumed
nexttile;
plot(scan_vals, mean_vals, 'o-', 'LineWidth', 1.5, 'MarkerSize', 6);
title('Mean', 'FontSize', title_fontsize, 'Interpreter', 'latex');
xlabel('$\alpha$ (degrees)', 'Interpreter', 'latex', 'FontSize', label_fontsize);
ylabel('$\kappa_1$', 'Interpreter', 'latex', 'FontSize', label_fontsize);
set(gca, 'FontSize', axis_fontsize);
grid on;

% 2. Variance
nexttile;
plot(scan_vals, var_vals, 's-', 'LineWidth', 1.5, 'MarkerSize', 6);
title('Variance', 'FontSize', title_fontsize, 'Interpreter', 'latex');
xlabel('$\alpha$ (degrees)', 'Interpreter', 'latex', 'FontSize', label_fontsize);
ylabel('$\kappa_2$', 'Interpreter', 'latex', 'FontSize', label_fontsize);
set(gca, 'FontSize', axis_fontsize);
grid on;

% 3. Skewness
nexttile;
plot(scan_vals, skew_vals, 'd-', 'LineWidth', 1.5, 'MarkerSize', 6);
title('Skewness', 'FontSize', title_fontsize, 'Interpreter', 'latex');
xlabel('$\alpha$ (degrees)', 'Interpreter', 'latex', 'FontSize', label_fontsize);
ylabel('$\kappa_3$', 'Interpreter', 'latex', 'FontSize', label_fontsize);
set(gca, 'FontSize', axis_fontsize);
grid on;

% 4. Binder Cumulant
nexttile;
plot(scan_vals, kappa4_vals, '^-', 'LineWidth', 1.5, 'MarkerSize', 6);
title('Binder Cumulant', 'FontSize', title_fontsize, 'Interpreter', 'latex');
xlabel('$\alpha$ (degrees)', 'Interpreter', 'latex', 'FontSize', label_fontsize);
ylabel('$\kappa_4$', 'Interpreter', 'latex', 'FontSize', label_fontsize);
set(gca, 'FontSize', axis_fontsize);
grid on;

% Super title (you can customize the string)
sgtitle('Cumulants of a simulated evolving distribution', ...
    'FontWeight', 'bold', 'FontSize', 18, 'Interpreter', 'latex');

%% === Helper: Cumulant Calculation ===
function kappa = computeCumulants(data, max_order)
    data = data(:);
    mu = mean(data);
    c = zeros(1, max_order);
    centered = data - mu;
    for n = 1:max_order
        c(n) = mean(centered.^n);
    end
    kappa = zeros(1, max_order);
    kappa(1) = mu;
    kappa(2) = c(2);
    kappa(3) = c(3);
    kappa(4) = c(4) - 3*c(2)^2;
    kappa(5) = c(5) - 10*c(3)*c(2);
    kappa(6) = c(6) - 15*c(4)*c(2) - 10*c(3)^2 + 30*c(2)^3;
end

%% === Helper: Skewed Normal Distribution ===
function x = skewnormrnd(mu, sigma, alpha, n)
    % Skew-normal using Azzalini's method
    delta = alpha / sqrt(1 + alpha^2);
    u0    = randn(n,1);
    v     = randn(n,1);
    u1    = delta * u0 + sqrt(1 - delta^2) * v;
    x     = mu + sigma * u1 .* sign(u0);
end
