MATLAB Answers

How to get index and color matrix from Data cursor

33 views (last 30 days)
Liu Ananiah
Liu Ananiah on 27 Oct 2020
Edited: Adam Danz on 13 Aug 2021
a = 1 : 10
b = 1.001 : 10.001
c = 1.002 : 10.002
a = [a;b;c];
a = a (:)';
cg = clustergram(a, 'Cluster', 'row', 'DisplayRange', ceil(max(abs(a))), 'ColumnPDist', 'chebychev', 'Linkage', 'complete', 'Colormap',colormap('jet'), 'DisplayRatio', 1/9)
Then, I click the Data Cursor and select a point.
Is there a way to get the index and color matrix to the workspace?

Accepted Answer

Adam Danz
Adam Danz on 27 Oct 2020
Edited: Adam Danz on 13 Aug 2021
"Is there a way to get the index and color matrix to the workspace?"
Here are 5 methods.
Method 1: use getDataTip
getDataTip is a function on the file exchange that extracts the datatip content and handles from a figure, axis, or an array of figures and axes in Matlab r2014 and later. See example file in the link.
Method 2: use getCurosrInfo()
Matlab's getCurosrInfo() returns the target and coordinates of each data tip in the figure but not the full text within the data tip.
datacursormode on
dcmObj = datacursormode(gcf);
dcmStruc = getCursorInfo(dcmObj);
Method 3: Use the data tip content menu
If you right-click a data tip and select Export Cursor Data to Workspace to return the target and coordinates of the selected data tip but not the full text within the data tip.
Method 4: Use the script below
This script is a section of getDataTip but only works in recent releases of Matlab that contain a DataTip object.
Unless the Data Tip content are loaded into an output variable, you shouldn't assign variables to the another workspace outside of a function.
Here's a simple script you can run any time from the command window or from a favorite command to capture the content of a Data Tip in the current figure. If the current figure does not have a Data Tip, a message will indicate so. If the current figure has more than one data tip, content from all data tips will be displayed.
% Get *all* datatip handles in figure
dth = findobj(gcf,'Type','DataTip');
if isempty(dth)
fprintf('There are no data tips in current figure.\n')
dtArray = [{newline};reshape([{dth.Content}',repelem({newline},numel(dth),1)]',[],1)];
Method 5: Use a ButtonDownFcn and reference the cdata
Datatips are not supported for standalone graphics such as clustergram, heatmap, etc. The datatip can be applied to the underlying image object (see this answer).
Here's a workaround that doesn't rely on datatip.
In short, it assigns a ButtonDownFcn to the main axes and produces a marker and text object when you click on the axes. The text shows the underlying RGB color values and they are also printed to the command window. Right-click the main axes to delete all pseudo data tips.
% Create clustergram
a = 1 : 10;
b = 1.001 : 10.001;
c = 1.002 : 10.002;
a = [a;b;c];
a = a (:)';
cg = clustergram(a, 'Cluster', 'row', ...
'DisplayRange', ceil(max(abs(a))), ...
'ColumnPDist', 'chebychev', ...
'Linkage', 'complete',...
'DisplayRatio', 1/9);
% Get fig & axis handles
cgfig = findall(0,'type','figure', 'Tag', 'Clustergram');
cgax = findobj(cgfig, 'type','axes','tag','HeatMapAxes');
% Get underlying image handle
cgImg = findall(cgax,'Type','Image','Tag','HeatMapImage');
% Confirm that datatip() is not supported
% datatip(cgax, .333, .5) % not supported as of r2020b
% Create an invisibly axes that lays on top of the main axes
axOverlay = copyobj(cgax, cgfig);
linkaxes([cgax, axOverlay])
linkprop([cgax, axOverlay], {'Parent','Units',...
'InnerPosition','OuterPosition','Position','View'}); % add more as needed
% Set ButtonDownFcn for figure
axOverlay.ButtonDownFcn = {@pseudoDataTip, cg, cgImg, axOverlay};
function pseudoDataTip(~,event,cg, cgImg, axOverlay)
% pseudoDataTip triggered by clicking the invisible axis on top of the clustergram heatmap.
% Add text similar to a data tip to clustergram axis including underlying RGB value.
% * event: Hit event data
% * cg is the clustergram obj
% * cgImg is the handle to the heatmap image within the clustergram obj
% * axOverlay is the invisible axes on top of the clustergram
% Only respond to left-mouse-clicks
if event.Button ~= 1
% Get mouse coordinate
xy = axOverlay.CurrentPoint(1,1:2);
% Find nearest coordinate to mouse click
xl = xlim(axOverlay);
yl = ylim(axOverlay);
xNorm = round((xy(1)-xl(1))/range(xl) * (size(cgImg.CData,2)-1) + 1);
yNorm = round((xy(2)-yl(1))/range(yl) * (size(cgImg.CData,1)-1) + 1);
% Get RGB value
cdata = cgImg.CData(yNorm,xNorm);
cmap = cg.Colormap;
clim = cgImg.Parent.CLim;
rgbIdx = round((cdata - clim(1))/range(clim) * (size(cmap,1)-1) + 1);
RGB = axOverlay.Colormap(rgbIdx,:);
% add marker and text box to clicked coordinate
hold(cgImg.Parent, 'on')
rgbstr = sprintf('RGB: [%.4g, %.4g, %.4g]', RGB);
fprintf([rgbstr,'\n']) % Print to command window
th = text(cgImg.Parent, xy(1), xy(2)-range(yl)*.03, rgbstr, ...
'BackgroundColor', [.996,.984,.730],'LineStyle','-', ...
plot(cgImg.Parent, xy(1), xy(2), 'ko','Markersize', 8, ...
% Assign cx menu to invisible axes if it wasn't already created
if isempty(axOverlay.ContextMenu)
fig = ancestor(cgImg,'figure');
cm = uicontextmenu(fig);
uimenu(cm, 'Text','Delete all RGB markers',...
'MenuSelectedFcn', @(~,~)delete(findall(cgImg.Parent,'Tag','RGBMarker')));
axOverlay.ContextMenu = cm;
Adam Danz
Adam Danz on 6 Nov 2020
Here are two lines from my answer (Method #5).
RGB = axOverlay.Colormap(rgbIdx,:);
% ...
plot(cgImg.Parent, xy(1), xy(2), 'ko','Markersize', 8, ...
The first line is the 1x3 RGB vector under the area where you clicked.
In the second line, that same 1x3 RGB vector is used to set the color of the pseudo datatip marker.
If you look at the GIF image in Method 5, the circular markers contain a black edge and a colored face that matches the color of the background.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!