How to get heatmap values in appdesigner?

Hi All!
I'm building an app, and I am using heatmap to visualize some data. I am plotting heatmap on a Panel. When I click on a cell of heatmap, it displays X and Y values. For further calculations I want to extract which cell the user clicked on. So what I need basically, is that when the user clicks on one of the heatmap cells fome function registers the coordinates (X,Y values) of the cell that have been clicked on. I don't know if it is possible with heatmap. Maybe there are other plot types with which it is easier to implement. Any solutions or siggestions?

3 Comments

Hi!
Thank you! It is not exactly what I was looking for but I might be able to go somewhere from here. What I would need actually sound very easy, still I have not found a solution for it. So for example, if I have a 5X7 matrix visualised with heatmap or an other function, and the user clickes on one of the cells, lets's say the cell in the third row and second column, the answer should be [3 2].
It would be simple but accessing the datacursor in heatmap is not simple and replacing it with a customizable datatip is still not supported to my knowledge. heatmap is notoriously difficult to customize and it's often necessary to use alternatives such as imagesc or histogram2 or surf to achieve customization.
Dave B's approach below (also see comments under that answer) is a simple alternative.
If you want to stick with heatmap, see methods 4 and 5 in the 2nd link Mario provided.

Sign in to comment.

 Accepted Answer

Dave B
Dave B on 13 Aug 2021
Edited: Dave B on 13 Aug 2021
Is this the sort of thing you're looking for?
h=imagesc(rand(5,7));
h.ButtonDownFcn=@(~,hit)disp(round(hit.IntersectionPoint(1:2)));
Note that this disp is just for testing, you'd probably do something more interesting there, and if it was more than a single line you can just pass in a function (or more likely method on your app) like any other callback.

6 Comments

I was thinking of something similar. However, the OP wants to return the index of the selected cell which requires an additional step to account for xdata and ydata that aren't indices. For example, clicking cell(1,1) of this image returns [5,3].
h=imagesc(5:2:13, 3:3:21, rand(5,7));
Modified version:
h=imagesc(4:0.1:4.6, 5:2:13, rand(5,7));
set(gca,'XTick',h.XData, 'YTick', h.YData) % for development purposes
h.ButtonDownFcn= @imgButtonDownFcn;
function imgButtonDownFcn(ImgObj, hit)
% find grid location of the click
[xGrid,yGrid] = meshgrid(ImgObj.XData, ImgObj.YData);
xyGrid = [xGrid(:), yGrid(:)];
xyDist = xyGrid - hit.IntersectionPoint(1:2);
[~, minIdx] = min(hypot(xyDist(:,1), xyDist(:,2)));
% return index of selected cell
xIdx = find(ImgObj.XData==xyGrid(minIdx,1),1);
yIdx = find(ImgObj.YData==xyGrid(minIdx,2),1);
fprintf('Selected cell idx: [%.0f,%.0f]\n',xIdx,yIdx)
end
% The callback fcn could be sped up by providing xyGrid
% as an input if the image data are not expected to change.
% The find() lines are slow and could be replaced with
% alternative approaches as well.
Also note that you can easily make imagesc plot look like heatmap plot. See this example:

You may want to consider flipping the y-axis too.

set(gca, 'ydir', 'normal')
Adam is absolutely correct, I only included a solution for the default x/y case.
Here's a slight tweak on his answer (which is perfectly fine) that shortens it a bit (@Adam Danz - correct me if I'm wrong!) by taking advantage of the fact that x and y are independent:
function imgButtonDownFcn(ImgObj, hit)
[~, xind] = min(abs(hit.IntersectionPoint(1) - ImgObj.XData));
[~, yind] = min(abs(hit.IntersectionPoint(2) - ImgObj.YData));
x = ImgObj.XData(xind);
y = ImgObj.YData(yind);
end
Yeah, the euclidean distance to grid centers in my comment (using hypot) isn't necessary and the first two lines in your comment above are more efficient. But since the OP wants to return the indicies rather than the X/YData, the last two lines in your comment above are not needed. Actually, I believe xind and yind are the solutions so it's much easier than my approach.
I also realized that my approach (and this one) isn't reliable for non-uniform grids as I incorrectly claimed in my solution. Imagine clicking within a large grid cell very close to a border and the bordering cell is very narrow. The click location would be closer to the neighboring grid cell center than it would be to the center of the larger cell that contained the click. But this doesn't matter if the user is trying to replicate heatmap since that function does not produce non-uniform grids.
The solution to support non-uniform grids would require pairs of <=, > conditions for x and y coordinates or a more fancy and probably less-efficient point-in-polygon approach.
Thank you @Adam Danz and @Dave B, this is exactly what I was lookig for!

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2019b

Community Treasure Hunt

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

Start Hunting!