How to do 3D plot using both contourf and surf plot?

23 views (last 30 days)
Hello matlab community,
I have two datasets ( Z = index and data=observation data) , both are 2D matrix and have different max/min.Both are defined at same X and Y location (this two also 2D matrix).
I want to show both this data in a 3d plot using surf and contourf command.
I have tried with the given code below and have shown you a plot that I am getting.I want to show both this data in a 3d plot using surf and contourf command.I want to plot a surface plot (to show 3d distribution) of the given "data" at the top of the index (Z data). That is 3d distribution of "data" and at z=0 I want to show the index data (Z data). So at xy plane (at z=0) of 3d distribution of "data", I want to plot the contourf of Index data.
I have tried with the code and have sown you a plot that I am getting (1st figure). You can see two plots are there in the figure i just want "pink and blue contourf" plot at z=0 of the other plot. (don't need to show xticks,zticks,yticks of contourf as both X,Y are same for two figure). I want a figure like the attached screenshot. I have also attached the data for better clarity of my question.
f=figure('color','w');
ax1 = axes;
surf(ax1,X(1:skip:end,1:skip:end,i),Y(1:skip:end,1:skip:end,i),data(1:skip:end,1:skip:end),data(1:skip:end,1:skip:end),'FaceAlpha',0.9, 'FaceColor','flat','EdgeColor','none');
xlim([0,76])
view(2)
colormap(ax1,'jet')
view(-15,50)
%shading interp
hold on
ax2 = axes;
contourf(ax2,X(1:skip:end,1:skip:end,i),Y(1:skip:end,1:skip:end,i),squeeze(Z(1:skip:end,1:skip:end,i)),'EdgeColor','none')
colormap(ax2,flipud(rgb))
xlim([0,76])
zticks([])
view(-15,150)
%linkaxes([ax1,ax2]);
axis equal
% Link two axes together
hLink = linkprop([ax1,ax2],{'XLim','YLim','ZLim','CameraUpVector','CameraPosition','CameraTarget'});
Any help would be appreciated and many thanks in advance.

Accepted Answer

Voss
Voss on 1 Mar 2022
It may be convenient to put both the surface and the contour in the same axes. Of course an axes can only have one colormap, so, since in this case you want to have different "colormaps" for each one, it is necessary to determine the colors of the surface explicitly (by indexing into the jet() colormap), then use the other colormap for the contour (I don't know what rgb is, so I used the 'cool' colormap to illustrate - you can use your rgb colormap there).
Your resulting code might look like this:
% loading data and making up variables
load('X.mat');
load('Y.mat');
load('Z.mat');
load('data.mat');
data = r;
skip = 1;
i = 1;
% get the jet colormap because we need to use its colors to set the
% surface's CData directly
cmap = jet();
% use the values of "data" to determine the corresponding indices into
% cmap:
min_data = min(min(data(1:skip:end,1:skip:end)));
max_data = max(max(data(1:skip:end,1:skip:end)));
% data == min_data -> index = 1 (i.e., first color in cmap)
% data == max_data -> index = size(cmap,1) (i.e., last color in cmap)
cmap_idx = round((data(1:skip:end,1:skip:end)-min_data)/(max_data-min_data)*(size(cmap,1)-1)+1);
% now handle NaNs because they can't be used as indices:
% make note of where cmap_idx is NaN:
nan_cdata = isnan(cmap_idx);
% set cmap_idx to 1 there (just has to be a valid index, doesn't matter
% what it is):
cmap_idx(nan_cdata) = 1;
% perform the indexing into cmap:
cdata = cmap(cmap_idx,:);
% now cdata is a matrix of RGB colors
% set cdata to NaN at the locations where the data was NaN:
cdata(nan_cdata,:) = NaN;
% finally reshape cdata to make it n-by-m-by-3:
cdata = reshape(cdata,[size(data(1:skip:end,1:skip:end)) 3]);
% begin plotting
f=figure('color','w');
ax1 = axes;
% make the surface, using cdata as the color matrix
surf(ax1,X(1:skip:end,1:skip:end,i),Y(1:skip:end,1:skip:end,i),data(1:skip:end,1:skip:end),cdata,'FaceAlpha',0.9, 'FaceColor','flat','EdgeColor','none');
% make the contour
hold on
contourf(ax1,X(1:skip:end,1:skip:end,i),Y(1:skip:end,1:skip:end,i),squeeze(Z(1:skip:end,1:skip:end,i)),'EdgeColor','none')
% set up the colormap for the contour
colormap(ax1,flipud(cool()));%flipud(rgb))
% set the view, etc.
xlim([0,76])
zticks([])
view(-15,150)
axis equal
  2 Comments
Subhodh Sharma
Subhodh Sharma on 2 Mar 2022
Edited: Subhodh Sharma on 2 Mar 2022
@_ many thanks for your help. I also want to show two colorbars related to the two data.
One colorbar for "data" of surf plot . Another for "Z" of contourf. If I am showing colorbar, it only shows the last contourf colorbar. But I want to retain both colorbar of "surf" and "contourf" with values showing actual range not "cdata" (which is matrix of rgb colors).
Thank you in advance.
Thank you man.
I want colorbar like this for the actual data.
Voss
Voss on 2 Mar 2022
With both the surface and the contour in a single axes, you can only have one proper colorbar.
But you can make your own "colorbar" by creating another axes and a surface in that axes showing the colors. See the last part of this code for how you might do that:
% loading data and making up variables
load('X.mat');
load('Y.mat');
load('Z.mat');
load('data.mat');
data = r;
skip = 1;
i = 1;
% get the jet colormap because we need to use its colors to set the
% surface's CData directly
cmap = jet();
% use the values of "data" to determine the corresponding indices into
% cmap:
min_data = min(min(data(1:skip:end,1:skip:end)));
max_data = max(max(data(1:skip:end,1:skip:end)));
% data == min_data -> index = 1 (i.e., first color in cmap)
% data == max_data -> index = size(cmap,1) (i.e., last color in cmap)
cmap_idx = round((data(1:skip:end,1:skip:end)-min_data)/(max_data-min_data)*(size(cmap,1)-1)+1);
% now handle NaNs because they can't be used as indices:
% make note of where cmap_idx is NaN:
nan_cdata = isnan(cmap_idx);
% set cmap_idx to 1 there (just has to be a valid index, doesn't matter
% what it is):
cmap_idx(nan_cdata) = 1;
% perform the indexing into cmap:
cdata = cmap(cmap_idx,:);
% now cdata is a matrix of RGB colors
% set cdata to NaN at the locations where the data was NaN:
cdata(nan_cdata,:) = NaN;
% finally reshape cdata to make it n-by-m-by-3:
cdata = reshape(cdata,[size(data(1:skip:end,1:skip:end)) 3]);
% begin plotting
f=figure('color','w');
ax1 = axes;
% make the surface, using cdata as the color matrix
surf(ax1,X(1:skip:end,1:skip:end,i),Y(1:skip:end,1:skip:end,i),data(1:skip:end,1:skip:end),cdata,'FaceAlpha',0.9, 'FaceColor','flat','EdgeColor','none');
% make the contour
hold on
contourf(ax1,X(1:skip:end,1:skip:end,i),Y(1:skip:end,1:skip:end,i),squeeze(Z(1:skip:end,1:skip:end,i)),'EdgeColor','none')
% set up the colormap for the contour
colormap(ax1,flipud(cool()));%flipud(rgb))
% set the view, etc.
xlim([0,76])
zticks([])
view(-15,150)
axis equal
% create colorbar for the contour:
cb_contour = colorbar();
% make another colorbar for the surface
% it's going to be 50 pixels to the right of the first colorbar
% (adjust it at will)
cb_units = get(cb_contour,'Units');
set(cb_contour,'Units','pixels');
cb_pos = get(cb_contour,'Position');
set(cb_contour,'Units',cb_units);
% 2nd colorbar axes:
cb_surface_axes = axes( ...
'Parent',gcf(), ...
'Units','pixels', ...
'Position',cb_pos+[50 0 0 0], ...
'Box','on', ...
'XTick',[], ...
'YAxisLocation','right', ...
'YLim',[min_data max_data]);
% 2nd colorbar colors (a surface):
N_colors = size(cmap,1);
cb_surface_surface = surface( ...
'Parent',cb_surface_axes, ...
'XData',[0 1], ...
'YData',linspace(min_data,max_data,N_colors), ...
'ZData',zeros(N_colors,2), ...
'CData',reshape(repmat(cmap,2,1),N_colors,2,3), ...
'EdgeColor','none');

Sign in to comment.

More Answers (1)

ONKAR
ONKAR on 1 Jun 2023
Obtain the 3 dimensional plot for following function using matlab z=(sin(underroot(x^2+y^2)))/(underroot(x^2+y^2)),-6<=x<=6, -6<=y<=6.

Categories

Find more on Colormaps in Help Center and File Exchange

Products


Release

R2017b

Community Treasure Hunt

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

Start Hunting!