From c9ed8be2f2e982e5258df52f3bbbef4c51cfa269 Mon Sep 17 00:00:00 2001 From: Karthik Chandrashekara Date: Sun, 24 Aug 2025 14:30:38 +0200 Subject: [PATCH] Modified PDF plotting to allow for plotting true histogram with and without normalization as default, with KDE as a choice. Modified function calls accordingly. --- Data-Analyzer/+Plotter/plotPDF.m | 58 +++++++++++++++---- .../BECToDroplets/plotAnalysisResults.m | 6 +- .../plotAnalysisResults.m | 7 ++- .../BECToStripes/plotAnalysisResults.m | 6 +- .../plotAnalysisResults.m | 6 +- .../BECToStripesToDroplets/runFullAnalysis.m | 4 +- 6 files changed, 66 insertions(+), 21 deletions(-) diff --git a/Data-Analyzer/+Plotter/plotPDF.m b/Data-Analyzer/+Plotter/plotPDF.m index 0ababf7..d960511 100644 --- a/Data-Analyzer/+Plotter/plotPDF.m +++ b/Data-Analyzer/+Plotter/plotPDF.m @@ -1,8 +1,11 @@ function plotPDF(dataCell, referenceValues, varargin) -%% plotPDF: Plots 2D heatmap of PDFs for grouped data +%% plotPDF: Plots 2D heatmap of PDFs for grouped data (Histogram or KDE) % % Usage: % Plotter.plotPDF(dataCell, referenceValues, ... +% 'PlotType', 'histogram', ... % 'histogram' (default) or 'kde' +% 'NumBins', 50, ... % number of histogram bins +% 'NormalizeHist', true, ... % normalize hist counts to probability density % 'Title', 'My Title', ... % 'XLabel', 'Scan Parameter', ... % 'YLabel', 'Data Values', ... @@ -31,42 +34,77 @@ function plotPDF(dataCell, referenceValues, varargin) addParameter(p, 'DataRange', [], @(x) isempty(x) || numel(x)==2); addParameter(p, 'XLim', [], @(x) isempty(x) || numel(x)==2); addParameter(p, 'Colormap', @jet); + addParameter(p, 'PlotType', 'histogram', @(x) any(validatestring(x,{'kde','histogram'}))); + addParameter(p, 'NumBins', 50, @isscalar); + addParameter(p, 'NormalizeHist', true, @islogical); parse(p, varargin{:}); opts = p.Results; N_params = numel(referenceValues); - % --- Determine y-grid for PDF --- + % --- Determine y-range --- if isempty(opts.DataRange) allData = cell2mat(dataCell(:)); - y_grid = linspace(min(allData), max(allData), opts.NumPoints); + y_min = min(allData); + y_max = max(allData); else - y_grid = linspace(opts.DataRange(1), opts.DataRange(2), opts.NumPoints); + y_min = opts.DataRange(1); + y_max = opts.DataRange(2); end - pdf_matrix = zeros(numel(y_grid), N_params); + if strcmpi(opts.PlotType,'kde') % KDE + y_grid = linspace(y_min, y_max, opts.NumPoints); + pdf_matrix = zeros(numel(y_grid), N_params); + else % Histogram + edges = linspace(y_min, y_max, opts.NumBins+1); + binCenters = (edges(1:end-1) + edges(2:end)) / 2; + pdf_matrix = zeros(numel(binCenters), N_params); + end % --- Compute PDFs --- for i = 1:N_params data = dataCell{i}; data = data(~isnan(data)); if isempty(data), continue; end - f = ksdensity(data, y_grid); - pdf_matrix(:, i) = f; + + if strcmpi(opts.PlotType,'kde') % KDE + f = ksdensity(data, y_grid); + pdf_matrix(:, i) = f; + else % Histogram + counts = histcounts(data, edges); + if opts.NormalizeHist + binWidth = edges(2) - edges(1); + counts = counts / (sum(counts) * binWidth); % probability density + end + pdf_matrix(:, i) = counts(:); + end end % --- Plot heatmap --- fig = figure(opts.FigNum); clf(fig); set(fig, 'Color', 'w', 'Position',[100 100 950 750]); - imagesc(referenceValues, y_grid, pdf_matrix); + if strcmpi(opts.PlotType,'kde') + imagesc(referenceValues, y_grid, pdf_matrix); + else + imagesc(referenceValues, binCenters, pdf_matrix); + end + set(gca, 'YDir', 'normal', 'FontName', opts.FontName, 'FontSize', opts.FontSize); xlabel(opts.XLabel, 'Interpreter', 'latex', 'FontSize', opts.FontSize, 'FontName', opts.FontName); ylabel(opts.YLabel, 'Interpreter', 'latex', 'FontSize', opts.FontSize, 'FontName', opts.FontName); title(opts.Title, 'Interpreter', 'latex', 'FontSize', opts.FontSize + 2, 'FontWeight', 'bold'); colormap(feval(opts.Colormap)); c = colorbar; - ylabel(c, 'PDF', 'Interpreter', 'latex', 'FontSize', opts.FontSize); + if strcmpi(opts.PlotType,'kde') + ylabel(c, 'PDF', 'Interpreter', 'latex', 'FontSize', opts.FontSize); + else + if opts.NormalizeHist + ylabel(c, 'Probability Density', 'Interpreter', 'latex', 'FontSize', opts.FontSize); + else + ylabel(c, 'Counts', 'Interpreter', 'latex', 'FontSize', opts.FontSize); + end + end if ~isempty(opts.XLim) xlim(opts.XLim); @@ -78,4 +116,4 @@ function plotPDF(dataCell, referenceValues, varargin) 'SaveDirectory', opts.SaveDirectory, ... 'SkipSaveFigures', opts.SkipSaveFigures); -end +end \ No newline at end of file diff --git a/Data-Analyzer/+Scripts/BECToDroplets/plotAnalysisResults.m b/Data-Analyzer/+Scripts/BECToDroplets/plotAnalysisResults.m index d47329f..c046569 100644 --- a/Data-Analyzer/+Scripts/BECToDroplets/plotAnalysisResults.m +++ b/Data-Analyzer/+Scripts/BECToDroplets/plotAnalysisResults.m @@ -79,7 +79,8 @@ Plotter.plotG2(compiled_results.full_g2_results.g2_all, ... 'Colormap', @Colormaps.coolwarm); %% ------------------ 3. PDF of max g² across transition ------------------ -Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, options.scan_reference_values, ... +Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ... + options.scan_reference_values, ... 'Title', options.titleString, ... 'XLabel', 'B (G)', ... 'YLabel', '$\mathrm{max}[g^{(2)}]$', ... @@ -88,7 +89,8 @@ Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_ 'SkipSaveFigures', options.skipSaveFigures, ... 'SaveFileName', 'PDF_MaxG2AcrossTransition.fig', ... 'SaveDirectory', figSaveDir, ... - 'NumPoints', 200, ... + 'NumBins', 20, ... + 'NormalizeHist', true, ... 'DataRange', [0 1.5], ... 'Colormap', @Colormaps.coolwarm, ... 'XLim', [min(options.scan_reference_values) max(options.scan_reference_values)]); diff --git a/Data-Analyzer/+Scripts/BECToDropletsToStripes/plotAnalysisResults.m b/Data-Analyzer/+Scripts/BECToDropletsToStripes/plotAnalysisResults.m index d47329f..e8ba6c7 100644 --- a/Data-Analyzer/+Scripts/BECToDropletsToStripes/plotAnalysisResults.m +++ b/Data-Analyzer/+Scripts/BECToDropletsToStripes/plotAnalysisResults.m @@ -79,7 +79,8 @@ Plotter.plotG2(compiled_results.full_g2_results.g2_all, ... 'Colormap', @Colormaps.coolwarm); %% ------------------ 3. PDF of max g² across transition ------------------ -Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, options.scan_reference_values, ... +Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ... + options.scan_reference_values, ... 'Title', options.titleString, ... 'XLabel', 'B (G)', ... 'YLabel', '$\mathrm{max}[g^{(2)}]$', ... @@ -88,12 +89,12 @@ Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_ 'SkipSaveFigures', options.skipSaveFigures, ... 'SaveFileName', 'PDF_MaxG2AcrossTransition.fig', ... 'SaveDirectory', figSaveDir, ... - 'NumPoints', 200, ... + 'NumBins', 20, ... + 'NormalizeHist', true, ... 'DataRange', [0 1.5], ... 'Colormap', @Colormaps.coolwarm, ... 'XLim', [min(options.scan_reference_values) max(options.scan_reference_values)]); - %% ------------------ 4. Cumulants across transition ------------------ Plotter.plotCumulants(options.scan_reference_values, ... {compiled_results.custom_g_results.mean_max_g2, compiled_results.custom_g_results.var_max_g2, compiled_results.custom_g_results.skew_max_g2_angle, compiled_results.custom_g_results.fourth_order_cumulant_max_g2}, ... diff --git a/Data-Analyzer/+Scripts/BECToStripes/plotAnalysisResults.m b/Data-Analyzer/+Scripts/BECToStripes/plotAnalysisResults.m index d47329f..c046569 100644 --- a/Data-Analyzer/+Scripts/BECToStripes/plotAnalysisResults.m +++ b/Data-Analyzer/+Scripts/BECToStripes/plotAnalysisResults.m @@ -79,7 +79,8 @@ Plotter.plotG2(compiled_results.full_g2_results.g2_all, ... 'Colormap', @Colormaps.coolwarm); %% ------------------ 3. PDF of max g² across transition ------------------ -Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, options.scan_reference_values, ... +Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ... + options.scan_reference_values, ... 'Title', options.titleString, ... 'XLabel', 'B (G)', ... 'YLabel', '$\mathrm{max}[g^{(2)}]$', ... @@ -88,7 +89,8 @@ Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_ 'SkipSaveFigures', options.skipSaveFigures, ... 'SaveFileName', 'PDF_MaxG2AcrossTransition.fig', ... 'SaveDirectory', figSaveDir, ... - 'NumPoints', 200, ... + 'NumBins', 20, ... + 'NormalizeHist', true, ... 'DataRange', [0 1.5], ... 'Colormap', @Colormaps.coolwarm, ... 'XLim', [min(options.scan_reference_values) max(options.scan_reference_values)]); diff --git a/Data-Analyzer/+Scripts/BECToStripesToDroplets/plotAnalysisResults.m b/Data-Analyzer/+Scripts/BECToStripesToDroplets/plotAnalysisResults.m index d47329f..c046569 100644 --- a/Data-Analyzer/+Scripts/BECToStripesToDroplets/plotAnalysisResults.m +++ b/Data-Analyzer/+Scripts/BECToStripesToDroplets/plotAnalysisResults.m @@ -79,7 +79,8 @@ Plotter.plotG2(compiled_results.full_g2_results.g2_all, ... 'Colormap', @Colormaps.coolwarm); %% ------------------ 3. PDF of max g² across transition ------------------ -Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, options.scan_reference_values, ... +Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_value, ... + options.scan_reference_values, ... 'Title', options.titleString, ... 'XLabel', 'B (G)', ... 'YLabel', '$\mathrm{max}[g^{(2)}]$', ... @@ -88,7 +89,8 @@ Plotter.plotPDF(compiled_results.custom_g_results.max_g2_all_per_scan_parameter_ 'SkipSaveFigures', options.skipSaveFigures, ... 'SaveFileName', 'PDF_MaxG2AcrossTransition.fig', ... 'SaveDirectory', figSaveDir, ... - 'NumPoints', 200, ... + 'NumBins', 20, ... + 'NormalizeHist', true, ... 'DataRange', [0 1.5], ... 'Colormap', @Colormaps.coolwarm, ... 'XLim', [min(options.scan_reference_values) max(options.scan_reference_values)]); diff --git a/Data-Analyzer/+Scripts/BECToStripesToDroplets/runFullAnalysis.m b/Data-Analyzer/+Scripts/BECToStripesToDroplets/runFullAnalysis.m index 64aeae7..18d32cb 100644 --- a/Data-Analyzer/+Scripts/BECToStripesToDroplets/runFullAnalysis.m +++ b/Data-Analyzer/+Scripts/BECToStripesToDroplets/runFullAnalysis.m @@ -4,14 +4,14 @@ dataSources = { struct('sequence', 'StructuralPhaseTransition', ... 'date', '2025/08/18', ... - 'runs', [8]) % specify run numbers as a string in "" or just as a numeric value + 'runs', [8, 9, 10, 11, 12, 13]) % specify run numbers as a string in "" or just as a numeric value }; options = struct(); % File / paths options.baseDataFolder = '//DyLabNAS/Data'; -options.measurementName = 'DropletsToStripes'; +options.measurementName = 'StripesToDroplets'; scriptFullPath = mfilename('fullpath'); options.saveDirectory = fileparts(scriptFullPath);