function [Rx, Ry] = extractThomasFermiRadii(folder_path, run_index, SuppressPlotFlag)    
    set(0,'defaulttextInterpreter','latex')
    set(groot, 'defaultAxesTickLabelInterpreter','latex'); set(groot, 'defaultLegendInterpreter','latex');
    
    format long
    
    % Load data
    Data   = load(sprintf(horzcat(folder_path, '/Run_%03i/psi_gs.mat'),run_index),'psi','Params','Transf','Observ');
    
    Params = Data.Params;
    Transf = Data.Transf; 
    Observ = Data.Observ; 
    
    if isgpuarray(Data.psi)
        psi = gather(Data.psi);
    else
        psi = Data.psi;
    end
    if isgpuarray(Data.Observ.residual)
        Observ.residual = gather(Data.Observ.residual); 
    else
        Observ.residual = Data.Observ.residual; 
    end
    
    % Axes scaling and coordinates in micrometers
    x                       = Transf.x * Params.l0 * 1e6; 
    y                       = Transf.y * Params.l0 * 1e6;
    z                       = Transf.z * Params.l0 * 1e6;

    dx = x(2)-x(1); dy = y(2)-y(1); dz = z(2)-z(1);
    
    % Compute probability density |psi|^2
    n                       = abs(psi).^2;
    nxz                     = squeeze(trapz(n*dy,2));
    nyz                     = squeeze(trapz(n*dx,1));
    nxy                     = squeeze(trapz(n*dz,3));
    
    state                   = nxy';

    % Fit
    fitResult               = fitThomasFermiProfile2D(state, x, y);
    Rx                      = fitResult.Rx;
    Ry                      = fitResult.Ry;

    if ~SuppressPlotFlag
        fig = figure(1); 
        clf
        set(gcf,'Position', [100, 100, 1800, 500])
        t = tiledlayout(1, 3, 'TileSpacing', 'compact', 'Padding', 'compact');

        % Original density plot
        nexttile;
        plot1 = pcolor(x, y, state);
        set(plot1, 'EdgeColor', 'none');
        colormap(gca, Helper.Colormaps.plasma())
        colorbar;
        xlabel('$x$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14)
        ylabel('$y$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14)
        title('Original Density', 'Interpreter', 'latex', 'FontSize', 16)
        axis square;
        set(gca, 'FontSize', 14);
    
        % Fitted TF profile plot
        nexttile;
        plot2 = pcolor(x, y, fitResult.fittedDensity);
        set(plot2, 'EdgeColor', 'none');
        colormap(gca, Helper.Colormaps.plasma())
        colorbar;
        xlabel('$x$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14)
        ylabel('$y$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14)
        title(sprintf('TF Fit: $R_x = %.2f\\,\\mu\\mathrm{m}$, $R_y = %.2f\\,\\mu\\mathrm{m}$', Rx, Ry), ...
                    'Interpreter', 'latex', 'FontSize', 16)
        axis square;
        set(gca, 'FontSize', 14);

                % 1D cuts through center
        nexttile;
        % Find index of center
        [~, ix0] = min(abs(x - fitResult.x0));
        [~, iy0] = min(abs(y - fitResult.y0));

        % X-cut: density along y = y0
        orig_cut_x = state(iy0, :);
        fit_cut_x  = fitResult.fittedDensity(iy0, :);

        % Y-cut: density along x = x0
        orig_cut_y = state(:, ix0);
        fit_cut_y  = fitResult.fittedDensity(:, ix0);

        % Plot both cuts
        plot(x, orig_cut_x, 'w-', 'LineWidth', 1.5); hold on
        plot(x, fit_cut_x,  'r--', 'LineWidth', 1.5)
        plot(y, orig_cut_y, 'w-', 'LineWidth', 1.5)
        plot(y, fit_cut_y,  'r--', 'LineWidth', 1.5)
        hold off
        axis square;
        legend({'$n(x)$', '$n_{\mathrm{TF}}(x)$', '$n(y)$', '$n_{\mathrm{TF}}(y)$'}, ...
               'Interpreter', 'latex', 'FontSize', 12, 'Location', 'northeast')

        xlabel('$x$ or $y$ ($\mu$m)', 'Interpreter', 'latex', 'FontSize', 14)
        ylabel('Density', 'Interpreter', 'latex', 'FontSize', 14)
        title('1-D Cut', 'Interpreter', 'latex', 'FontSize', 16)
        grid on
        set(gca, 'FontSize', 14)
    end
end 

function fitResult = fitThomasFermiProfile2D(state, xgrid, ygrid)
    % Fits a 2D Thomas-Fermi profile to the input BEC state
    %
    % Input:
    %   state   - 2D array (real density or complex wavefunction)
    %   xgrid   - vector of x-coordinates (size must match size(state,2))
    %   ygrid   - vector of y-coordinates (size must match size(state,1))
    %
    % Output (struct):
    %   fitResult.fittedDensity - 2D array of the fitted TF profile
    %   fitResult.n0            - peak density
    %   fitResult.x0, y0        - center coordinates
    %   fitResult.Rx, Ry        - Thomas-Fermi radii
    %   fitResult.params        - parameter vector [n0, x0, y0, Rx, Ry]

    % Compute density if input is a wavefunction
    if ~isreal(state)
        density = abs(state).^2;
    else
        density = state;
    end

    % Set up grid
    [X, Y]   = meshgrid(xgrid, ygrid);
    xy       = [X(:), Y(:)];
    n        = density(:);

    % Mask: ignore near-zero values
    mask     = n > max(n)*1e-3;
    xy       = xy(mask, :);
    n        = n(mask);

    % Initial guess: [n0, x0, y0, Rx, Ry]
    n0_guess = max(n);
    x0_guess = mean(xgrid(:));
    y0_guess = mean(ygrid(:));
    Rx_guess = (max(xgrid)-min(xgrid)) / 2;
    Ry_guess = (max(ygrid)-min(ygrid)) / 2;
    p0       = [n0_guess, x0_guess, y0_guess, Rx_guess, Ry_guess];

    % Bounds
    lb       = [0, min(xgrid), min(ygrid), 0, 0];
    ub       = [Inf, max(xgrid), max(ygrid), Inf, Inf];

    % TF 2D function
    tf2d     = @(p, xy) max(0, p(1) * (1 - ((xy(:,1)-p(2)).^2 / p(4)^2 + (xy(:,2)-p(3)).^2 / p(5)^2)));

    % Fit
    options  = optimoptions('lsqcurvefit','Display','off');
    pfit     = lsqcurvefit(tf2d, p0, xy, n, lb, ub, options);

    % Evaluate fitted profile over full grid
    fittedDensity = reshape(tf2d(pfit, [X(:), Y(:)]), size(X));

    % Return result
    fitResult.fittedDensity = fittedDensity;
    fitResult.n0 = pfit(1);
    fitResult.x0 = pfit(2);
    fitResult.y0 = pfit(3);
    fitResult.Rx = pfit(4);
    fitResult.Ry = pfit(5);
    fitResult.params = pfit;
end
