55 views (last 30 days)

Show older comments

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

Adam Danz
on 14 Jan 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.

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
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

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

Start Hunting!