Set marker alpha transparency based on point density for scatter plot

조회 수: 16 (최근 30일)
Emanuel Santos
Emanuel Santos 2024년 5월 8일
댓글: Emanuel Santos 2024년 5월 10일
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.

답변 (1개)

Tony
Tony 2024년 5월 8일
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
Emanuel Santos
Emanuel Santos 2024년 5월 10일
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.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Data Distribution Plots에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by