MATLAB Examples

Offsets and discarded data via pcolor and surf

This example shows how pcolor and surf offset data by one half pixel and discard one row and one column of data. This example shows the effect in pcolor, but the results will be the same with surf.

Contents

Generate data

For this example we need some data to work with. We'll use a 5-by-5 grid that we'll generate with peaks. The spatial resolution of this dataset is one unit in the x and y dimensions, similar to a climate data set of one-degree spatial resolution. Each data point will be centered on the half pixels:

x = 0.5:4.5;
y = 0.5:4.5;
[X,Y] = meshgrid(x,y);
Z = peaks(5);
Z([2,21]) = -4;

Plot scattered data

To start, use the scatter function to plot the gridded data points. I'm using Stephen Cobeldick's brewermap function to get the nice Reds colormap, and setting the background axis color to a light yellow (using rgb) to help us identify regions of missing data later.

figure('pos',[100 100 1200 425])
for k = 1:3
    subplot(1,3,k)
    hold on
    scatter(X(:),Y(:),60,Z(:),'filled','markeredgecolor','k')
    axis xy image
    axis([0 5 0 5])
    caxis([-6 8])
    set(gca,'color',rgb('light yellow'))
end

colormap(brewermap(256,'Reds'))

Compare imagesc, pcolor, and interpolated pcolor

To compare, plot the gridded data sets using imagesc, the default pcolor and pcolor with interpolated shading. The uistack function places newly-plotted gridded data under the scattered data points we plotted above.

subplot(131)
h1 = imagesc(x,y,Z);
uistack(h1,'bottom')
title 'imagesc'
xlabel 'Full dataset is plotted and centered properly.'

subplot(132)
h2 = pcolor(X,Y,Z);
uistack(h2,'bottom')
title 'pcolor or surf'
xlabel({'One row and one column of data are discarded';...
    'and all data are offset by one half pixel in x and y.'})

subplot(133)
h3 = pcolor(X,Y,Z);
uistack(h3,'bottom')
shading interp
title 'interpolated pcolor or surf'
xlabel({'Interpolating pcolor or surf fixes the offset,';...
    'but the half-pixel frame of no data remains.'})

Take a look a the center plot. The dark red data point that should be centered on (2.5,3.5) is represented by a dark red box centered on (3,4). And the bottom right data point is not represented at all by pcolor because pcolor with the default faceted shading discards the right-hand edge and the bottom row of data.

subplot(132)
t = text(2.75,3.75,'\rightarrow','rotation',45,...
    'vert','middle','horiz','center','color','b',...
    'fontsize',26);
plot(4.5,.5,'bo','markersize',20)

Dealing with NaNs

Many gridded data sets have missing data points, often represented by NaNs. Let's explore the effects of a NaN by setting a single data point in Z to NaN:

Z(12) = NaN;

Now re-run the same example as above:

figure('pos',[100 100 1200 425])
for k = 1:3
    subplot(1,3,k)
    hold on
    scatter(X(:),Y(:),60,Z(:),'filled','markeredgecolor','k')
    axis xy image
    axis([0 5 0 5])
    caxis([-6 8])
    set(gca,'color',rgb('light yellow'))

    % Highlight missing datapoint:
    plot(2.5,1.5,'bo','markersize',20)
end

colormap(brewermap(256,'Reds'))

subplot(131)
h1 = imagesc(x,y,Z);
uistack(h1,'bottom')
title 'imagesc'
xlabel({'Missing data point is falsely represented by a color';...
    'corresponding to the lowest value in the colormap.'})

subplot(132)
h2 = pcolor(X,Y,Z);
uistack(h2,'bottom')
title 'pcolor or surf'
xlabel({'Missing data point creates one clear pixel';...
    'which is offset in by one half pixel.'})

subplot(133)
h3 = pcolor(X,Y,Z);
uistack(h3,'bottom')
shading interp
title 'interpolated pcolor or surf'
xlabel({'Missing data point creates a neighborhood';...
    'of lost information.'})

Note that imagesc sets the missing data pixel to the color corresponding to the lowest value in the colormap (in this case, very light red). In effect, this is imagesc making up data without informing the viewer. That can be dangerous.

So which plotting function should I use?

The perennial unstatisfying answer to many questions in life: It all depends.

  • imagesc centers data nicely and also plots quite fast, but imagesc can only handle equally-spaced data and NaNs are surreptitiously represented by colors corresponding to other data in your dataset.
  • pcolor or surf with shading flat or the default shading faceted will offset data by half a pixel, and will completely ignore a row and a column of data. For large datasets this may not be a problem, but if you're working with smaller datasets where a missing column of data represents a significant percentage of the data you're plotting, pcolor may not be a good choice.
  • pcolor or surf with shading interp fixes the half-pixel offset, but the problem of missing data around the edges of the domain remains, and a single NaN with shading interp will take out a whole neighborhood of data.

Author Info

This example was written by Chad A. Greene of the University of Texas at Austin's Institute for Geophysics (UTIG), May 2015.