Modified PDF plotting to allow for plotting true histogram with and without normalization as default, with KDE as a choice. Modified function calls accordingly.

This commit is contained in:
Karthik 2025-08-24 14:30:38 +02:00
parent ebd31a91fb
commit c9ed8be2f2
6 changed files with 66 additions and 21 deletions

View File

@ -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);

View File

@ -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)]);

View File

@ -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}, ...

View File

@ -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)]);

View File

@ -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)]);

View File

@ -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);