Using data cursor with pcolor

85 views (last 30 days)
Mark Brandon
Mark Brandon on 13 Jan 2020
Edited: Adam Danz on 22 Apr 2021
If one uses the data cursor on a pcolor plot, you will see three coordinates, X, Y, and Z, but the Z coordinate is always zero. It took me some time to realize that pcolor is simply a variant of the surface function, with the view fixed from above (normal to the xy plane). Inspection of the data associated with the pcolor handle will show that the "Z" values are actually stored in the CData array, and the ZData array is otherwise set to zero. This is a clever arrangement in that plot is fixed at Z = 0, and the Z values are otherwise rendered as scaled colors. The downside is that this arrangement cripples the datacursor (i.e. the Z value is not correctly reported).
One solution is to set ZData = CData (see Figure 2 produced by the code below). The datacursor will now show local Z values. The downside is that pcolor surface is now fully 3D. As a consequence, other plot elements (contours, points, lines) may be masked by this 3D surface. You can see the 3D "pcolor" surface in figure 2 by rotating the plot or by running the command "view(3)" in the command window.
The simpliest "fix" would be to add "C" values to the datacursor. (Perhaps I should suggest this as a new feature.) You will find that if you click on the contour lines, that the datacursor reports back with a variable "Level", so this kind of fix is possible. Or I could write a custom modifcation to the datacursor.
My hope is that someone out there may have found a simplier fix.
Best,
Mark
% Create data
[X,Y] = meshgrid(-2:0.2:2,-2:0.2:2);
Z = X.*exp(-X.^2 - Y.^2);
% Pcolor plot without modification. Datacursor will show Z = 0. Superimposed contours work okay.
figure(1)
hold on
hP = pcolor(X,Y,Z); shading interp;
contour(X,Y,Z, 'Color', 'k', 'LineWidth', 1);
datacursormode on
% PColor plot with modification (ZData = CData), Z value in data cursor works, but contours are locally masked.
figure(2)
hold on
hP = pcolor(X,Y,Z); shading interp;
hP.ZData = hP.CData;
contour(X,Y,Z, 'Color', 'k', 'LineWidth', 1);
datacursormode on
  1 Comment
Adam Danz
Adam Danz on 14 Jan 2020
Edited: Adam Danz on 15 Jun 2020
+1; This problem is driving me crazy!
None of the follow attempts work and they all throw an error in r2019b.
Update: As of r2020a, some of the method below are now functional.
Base code
% Create data
[X,Y] = meshgrid(-2:0.2:2,-2:0.2:2);
Z = X.*exp(-X.^2 - Y.^2);
figure(1)
hold on
hP = pcolor(X,Y,Z); shading interp;
dt = datatip(hP,0,0);
Add row, use 'CData'
row = dataTipTextRow('C','CData');
hP.DataTipTemplate.DataTipRows(end+1) = row;
% Error using matlab.graphics.datatip.DataTipTemplate/set.DataTipRows
% Value must be a string scalar or a character vector with the name
% of a data property, such as 'XData', or it must be a vector or a function handle.
Add row, use hP.CData
row = dataTipTextRow('C',hP.CData);
hP.DataTipTemplate.DataTipRows(end+1) = row;
% Error using matlab.graphics.datatip.DataTipTemplate/set.DataTipRows
% Value must be compatible with the data source.
Replace Z-row with 'CData'
hP.DataTipTemplate.DataTipRows(3).Label = 'C';
hP.DataTipTemplate.DataTipRows(3).Value = 'CData';
% Error using matlab.graphics.datatip.DataTipTemplate/set.DataTipRows
% Value must be a string scalar or a character vector with the name
% of a data property, such as 'XData', or it must be a vector or a function handle.
Replace z-row with hp.CData
hP.DataTipTemplate.DataTipRows(3).Label = 'C';
hP.DataTipTemplate.DataTipRows(3).Value = hP.CData;
% Error using matlab.graphics.datatip.DataTipTemplate/set.DataTipRows
% Value must be compatible with the data source.

Sign in to comment.

Answers (2)

Adam Danz
Adam Danz on 22 Apr 2021
Edited: Adam Danz on 22 Apr 2021
@Mark Brandon, For 3D patches the color data does not have to correspond to the zdata. For example, You could have a 4D array where the first 3 dimensions are represented by x/y/z coordinates and the 4th dimension is represented by color at each coordinate. A simple example to imagine is a topography where x and y are longitude and latitude values, z is altitude, and color is population density.
By default, x/y/z values are shown in datatips with patch objects. I doubt datatips will be modified to suddently include cdata since that would change a lot of existing code that uses datatips.
The workaround in recent releases of Matlab is quite simple and can be placed in a function so that you can easily apply to pcolor objects.
Simply call the function datatip_z2cdata to update the datatip template
[X,Y] = meshgrid(-2:0.2:2,-2:0.2:2);
Z = X.*exp(-X.^2 - Y.^2);
figure(1)
hold on
hP = pcolor(X,Y,Z);
shading interp;
contour(X,Y,Z, 'Color', 'k', 'LineWidth', 1);
colorbar
datacursormode on
datatip_z2cdata(hP) % <----- adds cdata to datatip
% Add a datatip for demo purposes
datatip(hP,0.75,0);
Function to change ZData values to CData values
function datatip_z2cdata(h)
% h is a graphics object with a default X/Y/Z datatip and a
% CData property (e.g. pcolor). The Z portion of the datatip
% will be relaced with CData
% Generate an invisible datatip to ensure that DataTipTemplate is generated
dt = datatip(h,h.XData(1),h.YData(1),'Visible','off');
% Replace datatip row labeled Z with CData
idx = strcmpi('Z',{h.DataTipTemplate.DataTipRows.Label});
newrow = dataTipTextRow('C',h.CData);
h.DataTipTemplate.DataTipRows(idx) = newrow;
% Remove invisible datatip
delete(dt)
end
Alternatively, you could add the CData instead of replacing the ZData by getting rid of idx and setting h.DataTipTemplate.DataTipRows(end+1) = newrow;

Dani
Dani on 15 Jun 2020
% Create data
[X,Y] = meshgrid(-2:0.2:2,-2:0.2:2);
Z = X.*exp(-X.^2 - Y.^2);
% Plot
figure
hP = surf(X,Y,0*Z,Z); % surf instead of pcolor, Z is 0 -> no visibility problems for other objects
shading interp;
view(2) % force 2d view
hP.DataTipTemplate.DataTipRows(3).Value = hP.CData; % Overwrite default datatip value
  3 Comments
Alexander Plunkett
Alexander Plunkett on 22 Apr 2021
This works great, my only question now is how do I set it to work like this by default.
set(groot,'DefaultSurfaceDataTipTemplateDataTipRows(3)Value',3) wont work I assume...
Mark Brandon
Mark Brandon on 22 Apr 2021
I have not tried to work out a default arrangement for my "fix". My hope is that Mathworks would modify Matlab so that the data cursor worked with the color map.

Sign in to comment.

Categories

Find more on Geographic Plots in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!