Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab - Creating a heatmap to visualize density of 2D point data

Tags:

matlab

heatmap

Given a N x N array I want to generate a heat map that visualizes data in such a way:

enter image description here

Given the source image below I created a sparsely populated N X N array that contained the points listed below. 90 points in a 1000x800 array.

enter image description here

When researching online how to generate such a heatmap I stumbled on using colormap only to get disappointing results.

colormap('hot');   % set colormap
imagesc(points);        % draw image and scale colormap to values range
colorbar;  

I got rather disappointing results.

enter image description here

What other alternatives do I have to make my image above resemble the top one?

like image 501
Jebathon Avatar asked Oct 29 '17 02:10

Jebathon


People also ask

What should I plot on heatmap?

Heat maps are a standard way to plot grouped data. The basic idea of a heat map is that the graph is divided into rectangles or squares, each representing one cell on the data table, one row and one data set. The rectangle or square is color coded according to the value of that cell in the table.

How do I create a heatmap in Matlab?

Create a matrix of data. Then create a heatmap of the matrix values. Use custom labels along the x-axis and y-axis by specifying the first two input arguments as the labels you want. Specify the title and axis labels by setting properties of the HeatmapChart object.


2 Answers

There are a few different ways you can convert scattered or sparse matrix data into a heatmap that provides some better visualization of the point density. The examples I'll show here will start with scattered data, so if you already have data in a 2D matrix/histogram you can skip the initial steps...

Histogram:

If your scattered data is rather dense, a simple 2D histogram may be all you need. You can create a grid covering your scattered points (at a resolution of your choosing) and bin your data in the x and y directions using histcounts2:

% Normally distributed sample points:
x = randn(1, 10000);
y = randn(1, 10000);

% Bin the data:
pts = linspace(-4, 4, 101);
N = histcounts2(y(:), x(:), pts, pts);

% Plot scattered data (for comparison):
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));

% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, N);
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');

And here's the resulting plot:

enter image description here

Histogram + filtering:

If your scattered data is rather sparse, you can still create a histogram as above, but then filter the result to smooth it out. You could use imdilate if you have the Image Processing Toolbox, or create a filter matrix and use conv2. Here's an example of the latter:

% Normally distributed sample points:
x = randn(1, 100);
y = randn(1, 100);

% Bin the data:
pts = linspace(-3, 3, 101);
N = histcounts2(y(:), x(:), pts, pts);

% Create Gaussian filter matrix:
[xG, yG] = meshgrid(-5:5);
sigma = 2.5;
g = exp(-xG.^2./(2.*sigma.^2)-yG.^2./(2.*sigma.^2));
g = g./sum(g(:));

% Plot scattered data (for comparison):
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));

% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, conv2(N, g, 'same'));
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');

And here's the resulting plot:

enter image description here

Distance transform:

Starting with a sparse histogram from above, you could use bwdist from the Image Processing Toolbox to create a distance transform of the data. This would assign each pixel a value based on its distance from the nearest nonzero pixel.

Alternatively, you could avoid computing the 2D histogram by creating a grid covering your scattered points and computing the minimum distance from each grid point to one of your scattered points using pdist2 from the Statistics Toolbox. Here's an example (using the same sample data as above):

% Generate grid and compute minimum distance:
pts = linspace(-3, 3, 101);
[X, Y] = meshgrid(pts);
D = pdist2([x(:) y(:)], [X(:) Y(:)], 'euclidean', 'Smallest', 1);

% Plot scattered data:
subplot(1, 2, 1);
scatter(x, y, 'r.');
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]));

% Plot heatmap:
subplot(1, 2, 2);
imagesc(pts, pts, reshape(D, size(X)));
axis equal;
set(gca, 'XLim', pts([1 end]), 'YLim', pts([1 end]), 'YDir', 'normal');
colormap(flip(parula(), 1));

And here's the resulting plot:

enter image description here

like image 184
gnovice Avatar answered Oct 24 '22 09:10

gnovice


You first need to calculate the density of points on a xy grid. Here you are just plotting an "image version" of any scatter plot in matlab. So, before plotting, you need to process the data and obtaining the density map derived from you points. You could use for example the ksdensity function, that will estimate the density of points on a grid base. If this function is not available to you, there is a lot of function on the fileexchage that will do the same thing.

% get the x y coordinates of your points
[y,x] = find(points);
P = [x,y];

% estimate and plot the density
[Est,XY] = ksdensity(P);
imagesc(XY(:,1), XY(:,2),Est);
colormap('hot');
colorbar;
like image 41
beesleep Avatar answered Oct 24 '22 09:10

beesleep