# Help with 3D Data Contour Plot (Missing Values as Zeros)

89 views (last 30 days)
MS on 23 May 2024 at 17:25
Edited: Voss on 24 May 2024 at 18:12
I'm working with a 3D data set in MATLAB where two planes (y1 and y3) have 65 rows and 4 columns each. The third plane (y2) has only 26 rows and 4 columns. I need to create a contour plot where missing values in y2 are treated as zeros. (raw data attached)
Desired Functionality:
1. All three planes (y1, y2, y3) should have the same number of rows for consistent plotting.
2. Missing points (represented by NaN) in y2 should be filled with zeros (treated as valid data for the contour plot).
3. The original data in y2 (including non-NaN values) should be preserved.
4. The contour plot should accurately represent the data in all three planes.
5. stack output three contour plots based on split y values apllied in a 3D Plot
rewrite the code. any help appreciated.
clear all
close all
clc
set(0,'DefaultaxesFontSize',20);
set(0,'DefaulttextFontsize',20);
set(0,'DefaultaxesFontName','Times-Roman');
set(0,'DefaulttextFontName','Times-Roman');
set(0,'defaulttextinterpreter','latex')
set(0, 'DefaultAxesLineWidth', 4)
set(0,'DefaultAxesFontWeight','bold')
set(gcf, 'DefaultLineLineWidth', 4)
set(gca, 'DefaultLineLineWidth', 4)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
T = readtable('HB2B_4298.csv','PreserveVariableNames',true);%reading the data
Vx = table2array(T(:,:));%converting to arrays
TTT = Vx(:,11:14);%Pick your columns based on the data.EG., dsapce columns number = 13
A = unique(TTT,'rows');
Acell = splitapply(@(x){x}, A,findgroups(A(:,2)));%split group based on column 2=vy
Acell{:};
y1 = [Acell{1,:}];%first plane values
y2 = [Acell{2,:}];%second plane values
y3 = [Acell{3,:}];%third plane values
% y4 = [Acell{4,:}];%fourth plane values
y = {y1, y2, y3};
N = length(y);
rg = cell(N,1); cg = cell(N,1);
Rg = cell(N,1); Cg = cell(N,1);
Zg = cell(N,1);
for i= 1:N
rg{i} = linspace(min(y{i}(:,1)), max(y{i}(:,1)), 100);%x axis
cg{i} = linspace(min(y{i}(:,3)), max(y{i}(:,3)), 100);%z axis
[Rg{i}, Cg{i}] = meshgrid(rg{i}, cg{i});% x and z
Zg{i} = griddata(y{i}(:,1), y{i}(:,3), y{i}(:,4), Rg{i}, Cg{i});%important change acoriding to data
h = figure
% subplot(N,1,i);
[CC,HH]= contourf(Rg{i}, Cg{i}, Zg{i});%plot contour
set(HH,'LineColor','none')
colormap("default");
BB = colorbar
BB.Label.String = 'd spacing';%change
xlabel('X(mm)')%change
ylabel('Z(mm)')%change
saveas(h,sprintf('FIG%d.png',i));%change the FIG name to whatever the name you need
% Create contour plot with transparency (adjust alpha value)
end
h =
Figure (1) with properties: Number: 1 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
BB =
ColorBar with properties: Location: 'eastoutside' Limits: [1.0831 1.0848] FontSize: 18 Position: [0.8323 0.1109 0.0381 0.8152] Units: 'normalized' Use GET to show all properties
h =
Figure (2) with properties: Number: 2 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
BB =
ColorBar with properties: Location: 'eastoutside' Limits: [1.0839 1.0856] FontSize: 18 Position: [0.8323 0.1109 0.0381 0.8152] Units: 'normalized' Use GET to show all properties
h =
Figure (3) with properties: Number: 3 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
BB =
ColorBar with properties: Location: 'eastoutside' Limits: [1.0839 1.0858] FontSize: 18 Position: [0.8323 0.1109 0.0381 0.8152] Units: 'normalized' Use GET to show all properties
##### 3 CommentsShow 1 older commentHide 1 older comment
MS on 23 May 2024 at 18:15
sorry. HB2B_4298.csv file attached now
MS on 23 May 2024 at 19:54
clear all
close all
clc
set(0,'DefaultaxesFontSize',20);
set(0,'DefaulttextFontsize',20);
set(0,'DefaultaxesFontName','Times-Roman');
set(0,'DefaulttextFontName','Times-Roman');
set(0,'defaulttextinterpreter','latex')
set(0, 'DefaultAxesLineWidth', 4)
set(0,'DefaultAxesFontWeight','bold')
set(gcf, 'DefaultLineLineWidth', 4)
set(gca, 'DefaultLineLineWidth', 4)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
T = readtable('HB2B_4298.csv','PreserveVariableNames',true);%reading the data
Vx = table2array(T(:,:));%converting to arrays
TTT = Vx(:,11:14);%Pick your columns based on the data.EG., dsapce columns number = 13
A = unique(TTT,'rows');
Acell = splitapply(@(x){x}, A,findgroups(A(:,2)));%split group based on column 2=vy
Acell{:};
y1 = [Acell{1,:}];%first plane values
y2 = [Acell{2,:}];%second plane values
y3 = [Acell{3,:}];%third plane values
% y4 = [Acell{4,:}];%fourth plane values
% Ensure all planes have the same number of rows
maxRows = max([size(y1, 1), size(y2, 1), size(y3, 1)]);
y2 = [y2; nan(maxRows-size(y2,1), size(y2,2))]; % Append NaNs to y2 to match row size
% Copy missing xyz values from y1 to y2
missingIndices = isnan(y2(:, 1:3));
y2(missingIndices) = y1(missingIndices);
% Replace NaNs in the fourth column with zeros
y2(isnan(y2(:,4)), 4) = 0;
y = {y1, y2, y3};
N = length(y);
rg = cell(N,1); cg = cell(N,1);
Rg = cell(N,1); Cg = cell(N,1);
Zg = cell(N,1);
for i= 1:N
rg{i} = linspace(min(y{i}(:,1)), max(y{i}(:,1)), 100);%x axis
cg{i} = linspace(min(y{i}(:,3)), max(y{i}(:,3)), 100);%z axis
[Rg{i}, Cg{i}] = meshgrid(rg{i}, cg{i});% x and z
F = scatteredInterpolant(y{i}(:,1), y{i}(:,3), y{i}(:,4), 'natural'); % Use natural method for interpolation
Zg{i} = F(Rg{i}, Cg{i});
h = figure
[CC,HH]= contourf(Rg{i}, Cg{i}, Zg{i});%plot contour
set(HH,'LineColor','none')
colormap("default");
BB = colorbar
BB.Label.String = 'd spacing';%change
xlabel('X(mm)')%change
ylabel('Z(mm)')%change
saveas(h,sprintf('FIG%d.png',i));%change the FIG name to whatever the name you need
end
h =
Figure (1) with properties: Number: 1 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
BB =
ColorBar with properties: Location: 'eastoutside' Limits: [1.0831 1.0848] FontSize: 18 Position: [0.8323 0.1109 0.0381 0.8152] Units: 'normalized' Use GET to show all properties
Warning: Duplicate data points have been detected and removed - corresponding values have been averaged.
h =
Figure (2) with properties: Number: 2 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
BB =
ColorBar with properties: Location: 'eastoutside' Limits: [0 1] FontSize: 18 Position: [0.8323 0.1109 0.0381 0.8152] Units: 'normalized' Use GET to show all properties
h =
Figure (3) with properties: Number: 3 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
BB =
ColorBar with properties: Location: 'eastoutside' Limits: [1.0839 1.0858] FontSize: 18 Position: [0.8323 0.1109 0.0381 0.8152] Units: 'normalized' Use GET to show all properties
The code above resolves the problem, but I’m not satisfied with the interpolation(suggestions are welcome).
I’m seeking assistance to maintain the output contour in a 3D format, similar to slices in a 3D volume. I want to use the y-values to create a gap between the contour slices from the split group used in the code.
Any guidance would be greatly appreciated.

Sign in to comment.

### Accepted Answer

Voss on 24 May 2024 at 16:04
Edited: Voss on 24 May 2024 at 16:05
One way to present multiple contour plots as slices in the same axes is to specify the ZLocation of each contour object. See below for an example.
A consequence of doing that is that all the contours must share a common color scale. In this case, two of the contours have very little variation in their z-values (Zg{i}) compared to the other contour, so they contain only a single color.
set(0,'DefaultaxesFontSize',20);
set(0,'DefaulttextFontsize',20);
set(0,'DefaultaxesFontName','Times-Roman');
set(0,'DefaulttextFontName','Times-Roman');
set(0,'defaulttextinterpreter','latex')
set(0, 'DefaultAxesLineWidth', 4)
set(0,'DefaultAxesFontWeight','bold')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
T = readtable('HB2B_4298.csv','PreserveVariableNames',true);%reading the data
Vx = table2array(T(:,:));%converting to arrays
TTT = Vx(:,11:14);%Pick your columns based on the data.EG., dsapce columns number = 13
A = unique(TTT,'rows');
Acell = splitapply(@(x){x}, A,findgroups(A(:,2)));%split group based on column 2=vy
y1 = [Acell{1,:}];%first plane values
y2 = [Acell{2,:}];%second plane values
y3 = [Acell{3,:}];%third plane values
% y4 = [Acell{4,:}];%fourth plane values
% Ensure all planes have the same number of rows
maxRows = max([size(y1, 1), size(y2, 1), size(y3, 1)]);
y2 = [y2; nan(maxRows-size(y2,1), size(y2,2))]; % Append NaNs to y2 to match row size
% Copy missing xyz values from y1 to y2
missingIndices = isnan(y2(:, 1:3));
y2(missingIndices) = y1(missingIndices);
% Replace NaNs in the fourth column with zeros
y2(isnan(y2(:,4)), 4) = 0;
y = {y1, y2, y3};
N = length(y);
rg = cell(N,1); cg = cell(N,1);
Rg = cell(N,1); Cg = cell(N,1);
Zg = cell(N,1);
h = figure;
hold on
for i= 1:N
rg{i} = linspace(min(y{i}(:,1)), max(y{i}(:,1)), 100);%x axis
cg{i} = linspace(min(y{i}(:,3)), max(y{i}(:,3)), 100);%z axis
[Rg{i}, Cg{i}] = meshgrid(rg{i}, cg{i});% x and z
F = scatteredInterpolant(y{i}(:,1), y{i}(:,3), y{i}(:,4), 'natural'); % Use natural method for interpolation
Zg{i} = F(Rg{i}, Cg{i});
contourf(Rg{i}, Cg{i}, Zg{i}, 'ZLocation',i, 'LineStyle','none');%plot contour
colormap("default");
BB = colorbar;
BB.Label.String = 'd spacing';%change
xlabel('X(mm)')%change
ylabel('Z(mm)')%change
end
Warning: Duplicate data points have been detected and removed - corresponding values have been averaged.
view([40 40]) % adjust the view as needed
saveas(h,'FIG.png');%change the FIG name to whatever the name you need
##### 4 CommentsShow 2 older commentsHide 2 older comments
MS on 24 May 2024 at 16:49
Edited: MS on 24 May 2024 at 16:52
@Voss thanks. The regions in y2 do not have the data that should be plain white instead of interpolated values. Is there any other way to avoid the incorrect interpolation? I added NaNs and zeros to show no data at those regions. If you notice, y2 will have 26 rows instead of 65 rows like in y1 or y3 in the data. This is my problem. I do not want wrong interpolation as well. Maybe my logic is wrong.
Voss on 24 May 2024 at 18:03
Edited: Voss on 24 May 2024 at 18:12
I see what you mean: y2 only has data for the first and last x grid points.
You can introduce NaNs into y2 to make it the same size as y1, but you need to take care to put them in the correct rows. See below my use of ismember for that.
You can make a contour plot from data containing NaNs, but in this case, there are not enough non-NaN elements in y2 (only one grid on each side has non-NaNs) for contourf to render anything for the second slice. That is, each non-NaN element is connected only to NaN elements in the "Z"-direction (which is Y in the axes coordinates), so there's nothing contourf can render. To get around that, I replicate the data from the first and last grid to the two grids interior to them, so that those are connected to non-NaN elements and something can be rendered. I think the result looks reasonable.
(Also note that I removed the use of unique(_,'rows') at the top of of the code, so the ordering of the rows of y1, y2, y3 is different than it was in previous versions.)
set(0,'DefaultaxesFontSize',20);
set(0,'DefaulttextFontsize',20);
set(0,'DefaultaxesFontName','Times-Roman');
set(0,'DefaulttextFontName','Times-Roman');
set(0,'defaulttextinterpreter','latex')
set(0, 'DefaultAxesLineWidth', 4)
set(0,'DefaultAxesFontWeight','bold')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
T = readtable('HB2B_4298.csv','PreserveVariableNames',true,'NumHeaderLines',41);%reading the data
A = T{:,11:14};%Pick your columns based on the data.EG., dsapce columns number = 13
Acell = splitapply(@(x){x}, A, findgroups(A(:,2)));%split group based on column 2=vy
y1 = [Acell{1,:}];%first plane values
y2 = [Acell{2,:}];%second plane values
y3 = [Acell{3,:}];%third plane values
% y4 = [Acell{4,:}];%fourth plane values
% Construct a new y2, the same size as y1, keeping the values of y2(:,4)
% where y2(:,1) and y2(:,3) exist in y1, making the others NaNs
[ism,idx] = ismember(y2(:,[1 3]),y1(:,[1 3]),'rows');
V = y2(ism,4);
N = size(y1,1);
y2 = [y1(:,1) y2(1,2)*ones(N,1) y1(:,3) NaN(N,1)];
y2(idx(ism),4) = V;
% make sure y1, y2, and y3 all have the same X and Z coordinates now
assert(isequal(y1(:,[1 3]),y2(:,[1 3]),y3(:,[1 3])))
% X and Z grid points
NX = numel(unique(y1(:,1)));
NZ = numel(unique(y1(:,3)));
% reshape X and Z to matrices
X = reshape(y1(:,1),NX,NZ);
Z = reshape(y1(:,3),NX,NZ);
y = {y1, y2, y3};
N = length(y);
h = figure;
hold on
for i = 1:N
% reshape values to a matrix the same size as X and Z
V = reshape(y{i}(:,4),NX,NZ);
if i == 2
% to accommodate the missing data in the second slice,
% copy the 1st and last rows so that contourf can
% render something
V([2 4],:) = V([1 5],:);
end
contourf(X,Z,V,'ZLocation',y{i}(1,2),'LineStyle','none');%plot contour
end
colormap("default");
BB = colorbar;
BB.Label.String = 'd spacing';%change
xlabel('X(mm)')%change
ylabel('Y(mm)')%change
ylabel('Z(mm)')%change
view([40 40]) % adjust the view as needed
saveas(h,'FIG.png');%change the FIG name to whatever the name you need

Sign in to comment.

### Categories

Find more on Contour 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!