How to Create Surface Plot From Cells?

I am trying to creat a 2D colored surface plot, but I cannot get it to work.
I have two different cells which come from a .mat file and one vector. The vector V must have 37 values and the two cells are 1 x 37.
clc, clear
% Load Data
x = load('datasamp.mat');
V = x.v; %
A = x.as;
B = x.bs;
n=1;
for i = 1:37
while n <= length(A)
n = n + 1;
V(i) = 1:37
Z = [V; A(i); B(i)];
end
Z = [V;A;B];
surf(Z)
I know I can convert the cells to a matrix using cell2mat, but this has only caused more problems.
The first cell in A corrsponds to values taken at V(1) and the second to taken at V(2) and so on... I want it to plot all the data for V(i) for both A and B the problem is that each cell in A and B are 1000 data points so these are A(i) = 1x1000 and B(i)=1000x1. So i need V(i) to remain constant for all those points which i tried to do with a while loop and then move on to the next so say V(2) and do the same thing .
Does anyone know a way to get the data from the cells to create the surface plot with V on the x-axis A on the Y-axis and B used for the color bar scale?

10 Comments

@Austen Thomas: please upload your .mat file by clicking the paperclip button.
@Stephen Colbeldick Hi I am not going to be able to attach the file I stated arbitrary numbers for the size of the cells in the question it is actually much much larger.
If you have any ideas on how to fix this I would appreciate it
Thank you
Could you attach dummy data? We're in the dark here.
Hi Adam,
To make it a simpler cell can be:
A = {rand(1,10), rand(1,10), rand(1,10)}
B = {rand(10,1), rand(10,1), rand(10,1)}
V = 1:3
So the X axis will be V with a range of 1-3, the Y axis B with a range of 0-1 , and then A will be the color map.
For A(1) B(1) will need to be plotted at V(1) = 1 and so on.
I hope this helps!!
Thanks in advandce
I'm guessing 1:10 is supposed to be 1,10
I made one other mistake, the data in B is constent for all 3 iterations this really does not matter for the question so much though just some extra input
So B could be somethign like B = 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 repeated for each cell
Ok. If you're using surf(Z), Z is a [n by m] matrix defining the z (height / color) values of the surface plot while x = 1:n and Z = 1:m.
Judging your loops, would the first surface be defined like this?
Z = [(1:10)',A{1}',B{2}'];
I currently don’t have my desktop in front of me. But as long as the size of each cell is the same it should work except B should be B{1} for the first interval.
Does surf(Z) run without any issue? Even thought the data is in a cell or does it need to be converted to a matrix still to run?
" But as long as the size of each cell is the same it should work"
Yes, I can make it work, easily. By "work" I mean it doesn't break. But that doesn't mean it's doing what you want it to do.
"...except B should be B{1} for the first interval."
Right, my bad (typo).
"Does surf(Z) run without any issue? Even thought the data is in a cell or does it need to be converted to a matrix still to run?"
It needs to be a matrix. In my example above, I use curley brackets to extract the matrix from the cell array.

Sign in to comment.

 Accepted Answer

Based on the discussion in the comments under the question, I think this is the approach you're looking for. It works (i.e. there are no errors). But you should check that this works on a conceptual level.
A = {rand(1,10), rand(1,10), rand(1,10)};
B = {rand(10,1), rand(10,1), rand(10,1)};
V = 1:numel(A{1});
Z = [V',A{1}',B{1}];
figure();
surf(Z)
The second part could be put in a loop if you want to generate one surf() for each element in A & B.

9 Comments

I think the basic idea will work the only thing that won’t is that for my real data V is going to have distinct values say starting from 0:10:100
So the number of elements won’t actually be its length in my case it will have a length of 37
Do you believe this will still work if you started from 0:10:30 for the 3 different interval of V?
As long as V is the same length as A{i} and B{i}, it will work. If V is not the same length, I can't recommend an alternative because I don't know what you're trying to achieve. Maybe V isn't part of the surface in which case you would just need
surf([A{1}',B{1}])
The solution needs to come from a conceptual level and I don't know what Z (the surface) is supposed to represent.
it’s difficult to phrase over a message I’ll see if I can figure it out later. You got the basic idea. Thanks!
I always feel a little uneasy suggesting a solution that merely avoids an error without knowing that it's conceptually correct. Feel free to follow-up.
Hi Adam,
I figured the basic part of what i needed. Below was what I was looking for V is 1x37 cell array with the values i need. I do have a question for you though. The data i am plotting is so large that it exceeds the limits of surf() plot, and the surf() plot does not work for cell arrays do you know anyway around this? I want to create a 2D plot with the color bar on the side.
clc, clear
% Load Data
x = load('SamplData.mat');
A = x.a;
B = x.b;
C = x.c;
n = length(C{1});
V = arrayfun(@(v) v+zeros(1,n), 0:10:360, 'uniform', 0);
[X,Y,Z] = meshgrid(V,C,A);
surf(X,Y,Z)
colormap(hot(128));
colorbar;
"The data i am plotting is so large that it exceeds the limits of surf() plot"
You can probably decrease the resolution of the data. That can be done in a few ways.
% Indexing
A(1:2:end) %this removes every second sample from the data
%interp
interp1(1:numel(A),A,linspace(1,numel(A),1000))
% This reduces the data to 1000 samples spaning from the start
% to the end of your data.
"and the surf() plot does not work for cell arrays"
It looks like you're using meshgrid() to produce the inputs to surf() and those should be matrices. Where are the cell arrays coming from? Are there matricies stored within the cell array? That's easy to convert to double from cell.
I ended up doing something similar. I just made smaller samples for the data for example:
A{i}(1:1000)
Which gives the first 1000 data points and then I put that into a for loop to do it for each 1 x 37 cell. Is that similar to the resolution solution you are suggesting?
The problem I still have is I would like to plot the entire 1E6 or so datapoints. Or would your resolution technique help solve this?
That truncates the data so you never see what's happening past the 1000th data point. Maybe that's sufficient for what you're doing but why throw out everything past the 1000th data point? It doesn't sounds like a good idea. Again, this decision needs to be made at a conceptual level. What are you trying to show with the data?
It's like if a movie is too long and as the editor, you shorten it by merely stopping the movie at the 1-hour mark in the middle of a scene as opposed to cutting a fiew scenes here and there so people get to see the ending.
Another example: Let's say I'm plotting hourly weather measurements from Jan 1,1990 to June 6,2019. Your suggestion would merely cut all data after Jan 24, 1990. My suggestion would cut a few days here and there but you'd still have a data that spans those 19+ years.
The data is meant to show the spectral density on the color map for a changing voltage and frequency. Where voltage is on the Xaxis frequency on the Y. Which will allow the viewer to see the greatest intensity for a given voltage and frequency. Where the X axis will be 0-300 and y will be 1000-25e6

Sign in to comment.

More Answers (0)

Categories

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