Set marker alpha transparency based on point density for scatter plot

16 vues (au cours des 30 derniers jours)
Emanuel Santos
Emanuel Santos le 8 Mai 2024
Commenté : Emanuel Santos le 10 Mai 2024
Hi everyone,
I am using a custom function to calculate the density of point for a scatter plot based on the bin size. Below is the example of the plot generated by the code.
In the above code, the color is set such that point around the center of bin with high point density will be colored brownm, and the lower desity will be blue. The point in the bithween will be colored in accordance to the heatmap gradiente.
Problem:
  1. Similarly to setting the color as a function fo the point density, I would like to set the alpha trasnparency of the marker edges and faces based on the point density. So the plot would like somewhat like below. Basically, what I want to accomplishe is that as the marker color gravitates towards the blue color, I would like to the decrease the transparency level of the marker, at the same time that the marker taht are Brown will be 100% opaque. So, simply put, I would like to change the 'MarkerEdgeAlpha' as a function of the point count density.
2. Change point cound density to relative frequency. Below is a figure where this is exemplified (Source Fig. 2 in Nature Paper).
Following is my script, which contain the in file function. This is a modification of the file prepared by @Lukas and shared at Original File.
clear all
close all
function outfile = heatscatter(X, Y, outpath, outname, numbins, markersize, marker, plot_colorbar, plot_lsf, xlab, ylab, title)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% heatscatter(X, Y, outpath, outname, numbins, markersize, marker, plot_colorbar, plot_lsf, xlab, ylab, title)
% mandatory:
% X [x,1] array containing variable X
% Y [y,1] array containing variable Y
% outpath path where the output-file should be saved.
% leave blank for current working directory
% outname name of the output-file. if outname contains
% filetype (e.g. png), this type will be used.
% Otherwise, a pdf-file will be generated
% optional:
% numbins [double], default 50
% number if bins used for the
% heat3-calculation, thus the coloring
% markersize [double], default 10
% size of the marker used in the scatter-plot
% marker [char], default 'o'
% type of the marker used in the scatter-plot
% plot_colorbar [double], boolean 0/1, default 1
% set whether the colorbar should be plotted
% or not
% plot_lsf [double], boolean 0/1, default 1
% set whether the least-square-fit line
% should be plotted or not (together with
% the correlation/p-value of the data
% xlab [char], default ''
% lable for the x-axis
% ylab [char], default ''
% lable for the y-axis
% title [char], default ''
% title of the figure
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% mandatory
if ~exist('X','var') || isempty(X)
error('Param X is mandatory! --> EXIT!');
end
if ~exist('Y','var') || isempty(Y)
error('Param Y is mandatory! --> EXIT!');
end
if ~exist('outpath','var')
error('Param outpath is mandatory! --> EXIT!');
end
if ~exist('outname','var') || isempty(outname)
error('Param outname is mandatory! --> EXIT!');
end
%%%% optional
if ~exist('numbins','var') || isempty(numbins)
numbins = 50;
else
% force number, not char input
numbins = str2double(numbins);
end
if ~exist('markersize','var') || isempty(markersize)
markersize = 10;
else
% force number, not char input
markersize = str2double(markersize);
end
if ~exist('marker','var') || isempty(marker)
marker = 'o';
end
if ~exist('plot_colorbar','var') || isempty(plot_colorbar)
plot_colorbar = 1;
end
if ~exist('plot_lsf','var') || isempty(plot_lsf)
plot_lsf = 1;
end
if ~exist('xlab','var') || isempty(xlab)
xlab = '';
end
if ~exist('ylab','var') || isempty(ylab)
ylab = '';
end
if ~exist('title','var') || isempty(title)
title = '';
end
[values, centers] = hist3([X Y], [numbins numbins]);
centers_X = centers{1,1};
centers_Y = centers{1,2};
binsize_X = abs(centers_X(2) - centers_X(1)) / 2;
binsize_Y = abs(centers_Y(2) - centers_Y(1)) / 2;
bins_X = zeros(numbins, 2);
bins_Y = zeros(numbins, 2);
for i = 1:numbins
bins_X(i, 1) = centers_X(i) - binsize_X;
bins_X(i, 2) = centers_X(i) + binsize_X;
bins_Y(i, 1) = centers_Y(i) - binsize_Y;
bins_Y(i, 2) = centers_Y(i) + binsize_Y;
end
scatter_COL = zeros(length(X), 1);
onepercent = round(length(X) / 100);
for i = 1:length(X)
if (mod(i,onepercent) == 0)
fprintf('.');
end
last_lower_X = NaN;
last_higher_X = NaN;
id_X = NaN;
c_X = X(i);
last_lower_X = find(c_X >= bins_X(:,1));
if (~isempty(last_lower_X))
last_lower_X = last_lower_X(end);
else
last_higher_X = find(c_X <= bins_X(:,2));
if (~isempty(last_higher_X))
last_higher_X = last_higher_X(1);
end
end
if (~isnan(last_lower_X))
id_X = last_lower_X;
else
if (~isnan(last_higher_X))
id_X = last_higher_X;
end
end
last_lower_Y = NaN;
last_higher_Y = NaN;
id_Y = NaN;
c_Y = Y(i);
last_lower_Y = find(c_Y >= bins_Y(:,1));
if (~isempty(last_lower_Y))
last_lower_Y = last_lower_Y(end);
else
last_higher_Y = find(c_Y <= bins_Y(:,2));
if (~isempty(last_higher_Y))
last_higher_Y = last_higher_Y(1);
end
end
if (~isnan(last_lower_Y))
id_Y = last_lower_Y;
else
if (~isnan(last_higher_Y))
id_Y = last_higher_Y;
end
end
scatter_COL(i) = values(id_X, id_Y);
alpha_COL(i) = sqrt(values(id_X)^2+values(id_Y)^2);
end
f = figure();
sct=scatter(X, Y, markersize, scatter_COL,"filled");
if (plot_colorbar)
colorbar;
end
if (plot_lsf)
[r,p] = corr(X, Y);
str = {sprintf('corr: %.3f', r), sprintf('pval: %d', p)};
l = lsline;
set(l, 'Color', 'k');
annotation('textbox', [0.14 0.80 0.1 0.1], 'String', str, 'EdgeColor', 'none');
end
if (~isempty(xlab))
xlabel(xlab);
end
if (~isempty(ylab))
ylabel(ylab);
end
if (~isempty(title))
title(title);
end
[p,n,r] = fileparts(outname);
if (isempty(r))
r = '';
end
set(gca,'FontSize',12,'fontname','Samsung Sans','color','w')
outname = strcat(p,n,r);
f.Position = [100 100 400 400];
set(gcf, 'PaperSize', [2 4]);
set(gcf,'windowstyle','docked') % or use a specific fig handle
colormap jet(64)
cb = colorbar;
cb.Label.String = 'Density by Point Count';
cb.FontName = 'Samsung Sans';
cb.Label.FontSize = 12;
figname = [num2str(outname) 'Oscilogram.jpg'];
exportgraphics(f,figname,'Resolution',600);
outfile = fullfile(outpath, outname);
% saveas(f, outfile);
end
X1=randn(10000,1);
X2=randn(10000,1);
X3=randn(10000,1);
X=X1.^2+X2.*X3;
Y=randn(10000,1);
numbinss=80;
f=heatscatter(X,Y,"C:\",'X-Y Scatter Variable Alpha',num2str(numbinss),'15','o',1,0,'X-axis','Y-axis');
Please let me know if more clarification is required and I will be happy to provide.
Thank you so much for the help.

Réponses (1)

Tony
Tony le 8 Mai 2024
Not sure about changing marker transparency, but an indirect way is to change the 'lightness' of the marker color
c_max = [0 0 1];
LIGHTNESS_MAX = 0.9; % 1 will be white, and potentially hard to see
pt_values = 0:0.1:1;
pt_min = min(pt_values);
pt_max = max(pt_values);
pt_colours = 1 - (1 - LIGHTNESS_MAX * (pt_max - pt_values') / (pt_max - pt_min)) * (1 - c_max); % range of base color with lightness varying from base color to max lightness parameter
figure(); hold on;
for i = 1:numel(pt_values)
plot(pt_values(i), pt_values(i), 'Color', pt_colours(i,:), 'Marker', '.', 'MarkerSize', 16);
end
  1 commentaire
Emanuel Santos
Emanuel Santos le 10 Mai 2024
Hi Tony, thank you for your input. I am not being able to translate that into my scatter plot. Still strugling to get it as I would like.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Data Distribution Plots dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by