I have a 2d matrix A (100 x 100) where each row contains a signal to be plot.
I want to plot all of the signals in the same figure with different color for each row. How can I do this easily?
If you actually look at the documentation for plot you'll see that if you pass it a matrix, it will plot each column as a separate plot object on the same axes. As such you can simply pass the transpose of your data to plot.
% Example data
A = magic(10);
% Create a plot for each row
hplot = plot(A.');
This will plot each signal using the next plot color.
If you want to ensure that you have all different colors, you can use a colormap (such as parula) to explicitly set a different color per plot.
set(hplot, {'Color'}, num2cell(parula(size(A, 1)), 2))
Update
If you want to label your plots you could simply use legend to do this.
displaynames = arrayfun(#(x)sprintf('Plot %d', x), 1:size(A, 1), 'uni', 0);
set(hplot, {'DisplayName'}, displaynames.');
legend(hplot)
Or if you have too many plots to reasonably fit within a legend you can create an interactive plot that highlights a given plot when you mouseover it. Here is an example of such a thing.
htitle = title('');
set(gcf, 'WindowButtonMotionFcn', #(s,e)motionCallback(hittest(s)))
motionCallback(hplot(1));
function motionCallback(plt)
% Don't do anything if not a line object
[tf, ind] = ismember(plt, hplot);
if ~tf; return; end
set(hplot, 'linewidth', 1)
set(plt, 'LineWidth', 3)
set(htitle, 'String', sprintf('SelectedPlot: %d', ind))
drawnow
end
And the result
Related
this might come as an eco in this forum but I couldn't find a solution that I could apply to my problem. I have a cell of res_A1 of size (1x500) and in each cell there is a vector (1xlength) where length varies. I would like to plot in the same graph every vector or maybe a handful of them. All lines can be in the same color. I have tried following but the graph make no sense
data=res_A1(1,:,end);
plot(cell2mat(data)');
Also I would like to plot the average of the 500 vectors, preferably this should be in the same graph in another color. Is there a nice way of doing this?
You can use cat to combine the vectors along the first dimension. Then you can pass the transpose of this matrix to plot and each column will be plotted as it's own plot.
plot(cat(1, data{:}).');
If we create some example data, this will yield.
data = arrayfun(#(x)rand(1,10), ones(1, 5), 'uni', 0);
plot(cat(1, data{:}).');
If you want specific ones (i.e. [1 3 5]), you can replace : above with the indices of the ones you want.
plot(cat(1, data{[1 3 5]}).');
If you want to plot the average, simply use mean on the result of the call to cat.
avg = mean(cat(1, data{:}), 1);
plot(avg);
And if you wanted it in the same plot:
alldata = cat(1, data{:});
avg = mean(alldata, 1);
% Plot all of the curves
plot(alldata.');
hold on
% Plot the average curve
plot(avg, 'LineWidth', 3, 'Color', [0.5 0.5 0.5], 'LineStyle', '--')
Update
If your data is all different lengths, You have two options, you could plot everything with a loop.
hax = axes;
hold(hax, 'on');
for k = 1:numel(data)
plot(data{k}, 'Parent', hax);
end
Or you could still try to combine everything into one matrix, padding with NaN values.
% Find the longest vector length
maxlength = max(cellfun(#(x)numel(x), data));
alldata = nan(maxlength, numel(data));
for k = 1:numel(data)
alldata(1:numel(data{k}),k) = data{k};
end
Then you can plot this and take the mean using nanmean.
plot(alldata);
avg = nanmean(alldata, 2);
I have datasets for 5 different frequencies in a matrix and I want to illustrate them using plot, hist and mesh. However, each plot type is using different colormaps (see picture), so I need a legend for every plot.
Is there a way to set the same colormap for all plot types, or specify one for each of them? Another thing thats strange: I can set the colormap for hist using the figure tools for example, but not for the normal plot. For the mesh I have to use a hold on loop, so I guess setting the color here is different from defining a colormap?
Edit:
Here is a minimal example. Its still not working, see comments in the code below.
clear all;
close all;
clc;
% make up some data with the original format
freqLen = 5;
data = zeros(10, 3, 3, freqLen);
data(:, :, :, 1) = rand(10, 3, 3);
data(:, :, :, 2) = rand(10, 3, 3)+1;
data(:, :, :, 3) = rand(10, 3, 3)+2;
data(:, :, :, 4) = rand(10, 3, 3)+3;
data(:, :, :, 5) = rand(10, 3, 3)+4;
% reshape data so we get a vector for each frequency
dataF = reshape(data, [10*3*3, freqLen]);
% prepare colors for plot, try to get 5 colors over the range of colormap
% but I get wrong colors using both methods below!
%cols = colormap(jet);
%cols = cols(1:round(length(cols)/length(freqGHz)):end, :);
cols = jet(freqLen);
% plot samples in 3D
figure('Position', [0 0 1000 1000]);
subplot(211);
hold on;
for iF = 1:freqLen
dataThisF = dataF(:, iF);
data3D = reshape(dataThisF, [10*3, 3]);
mesh(data3D);
% try to give each "holded" mesh a different color. Not working!
% after the loop, all meshes have the last color
set(get(gca, 'child'), 'FaceColor', 'w', 'EdgeColor', cols(iF, :));
end
view(60, 20);
% plot samples
subplot(223);
hold on;
for iF = 1:freqLen
% the loop is not avoidable
% because matlab maps the colors wrong when plotting as a matrix
% at least its not using the colormap colors
plot(dataF(:, iF), 'Color', cols(iF, :));
end
% plot histogram
subplot(224);
% actually the only one which is working as intended, horray!
hist(dataF, 50);
How can I give a holded mesh a single color, different from the others? How can I map the correct jet colormap when plotting a matrix using simple line plot, or at least get 5 colors from the jet colormap (jet(5) give 5 different colors, but not from start to end)?
What you are talking about is mainly the ColorOrder property (and not the colormap of the figure).
The link for the colororder given just above will explain you how to force Matlab to use a given set of colors for all the plots. It works perfectly fine for plot. You wouldn't need a loop, just define the DefaultColororder property of the figure before the plots then plot all your series in one single call, Matlab will assign the color of each plot according to the order you defined earlier.
For mesh and hist it is not that simple unfortunately, so you will have to run a loop to specify the color or each graphic object. To modify a graphic object property (like the color) after it has been created, you have to use the set method, or even the direct dot notation if you're using a Matlab version >= 2014b. For both methods you needs to have the handle of the graphic object, so usually the easiest when you know you'll need that is to retrieve the graphic object handle at the time of creation*.
*instead of dirty hack like get(gca, 'child'). This is quite prone to errors and as a matter of fact was wrong in your case. Your code wouldn't color properly because you were not getting the right graphic handle this way.
The code below plots all your graphs, retrieve the handle of each graphic object, then assign the colors in the final loop.
%// Get a few colors
cols = jet(freqLen);
% plot samples in 3D
figure('Position', [0 0 1000 1000]);
set( gcf , 'DefaultAxesColorOrder',cols) %// set the line color order for this figure
subplot(2,1,1,'NextPlot','add'); %// 'NextPlot','add' == "hold on" ;
for iF = 1:freqLen
dataThisF = dataF(:, iF);
data3D = reshape(dataThisF, [10*3, 3]);
h.mesh(iF) = mesh(data3D) ; %// plot MESH and retrieve handles
%// You can set the color here direct, or in the last final "coloring" loop
%// set( h.mesh(iF) , 'FaceColor', 'w', 'EdgeColor', cols(iF, :));
end
view(60, 20);
%// plot samples
subplot(223);
h.plots = plot(dataF); %// plot LINES and retrieve handles
%// plot histogram
subplot(224);
[counts,centers] = hist(dataF, 50 ) ; %// get the counts values for each series
h.hist = bar(centers,counts) ; %// plot HISTOGRAM and retrieve handles
%// now color every series with the same color
for iF = 1:freqLen
thisColor = cols(iF, :) ;
set( h.mesh(iF) , 'EdgeColor' , thisColor , 'FaceColor', 'w' );
set( h.hist(iF) , 'EdgeColor' , thisColor , 'FaceColor' , thisColor )
%// this is actually redundant, the colors of the plots were already right from the
%// beginning thanks to the "DefaultColorOrder" property we specified earlier
set( h.plots(iF) , 'Color' , thisColor )
end
Will land you the following figure:
UPDATE: The original question asked
Is there a way to set the same colormap for all plot types, or specify one for each of them?
this answer, answers that question with colormap taken to mean colormap in MATLAB literally.
You can set the colormap for a figure using colormap. You could use one of the many built in colormaps or specify your own.
An example using mesh and the builtin hsv colormap could be
figure;
mesh(data);
colormap(hsv);
This would apply a colormap based on
to your figure. You can also create your own colormap like
map = [1, 0, 0,
1, 1, 1,
0, 1, 0,
0, 0, 0];
colormap(map);
which would create a colormap with the colours Red, White, Blue and Black.
The MATLAB documentation contains extensive information on the use of colormap.
I have matrices x1, x2, ... containing variable number of row vectors.
I do successive plots
figure
hold all % or hold on
plot(x1')
plot(x2')
plot(x3')
Matlab or octave normally iterates through ColorOrder and plot each line in different color. But I want each plot command to start again with the first color in colororder, so in default case the first vector from matrix should be blue, second in green, third in red etc.
Unfortunately I cannot find any property related to the color index niether another method to reset it.
Starting from R2014b there's a simple way to restart your color order.
Insert this line every time you need to reset the color order.
set(gca,'ColorOrderIndex',1)
or
ax = gca;
ax.ColorOrderIndex = 1;
see:
http://au.mathworks.com/help/matlab/graphics_transition/why-are-plot-lines-different-colors.html
You can shift the original ColorOrder in current axes so that the new plot starts from the same color:
h=plot(x1');
set(gca, 'ColorOrder', circshift(get(gca, 'ColorOrder'), numel(h)))
plot(x2');
You can wrap it in a function:
function h=plotc(X, varargin)
h=plot(X, varargin{:});
set(gca, 'ColorOrder', circshift(get(gca, 'ColorOrder'), numel(h)));
if nargout==0,
clear h
end
end
and call
hold all
plotc(x1')
plotc(x2')
plotc(x3')
Define a function that intercepts the call to plot and sets 'ColorOrderIndex' to 1 before doing the actual plot.
function plot(varargin)
if strcmp(class(varargin{1}), 'matlab.graphics.axis.Axes')
h = varargin{1}; %// axes are specified
else
h = gca; %// axes are not specified: use current axes
end
set(h, 'ColorOrderIndex', 1) %// reset color index
builtin('plot', (varargin{:})) %// call builtin plot function
I have tested this in Matlab R2014b.
I found a link where a guy eventually solves this. He uses this code:
t = linspace(0,1,lineCount)';
s = 1/2 + zeros(lineCount,1);
v = 0.8*ones(lineCount,1);
lineColors = colormap(squeeze(hsv2rgb(t,s,v)))
ax=gca
ax.ColorOrder = lineColors;
Which should work for you assuming each of your matrices has the same number of lines. If they don't, then I have a feeling you're going to have to loop and plot each line separately using lineColors above to specify an RBG triple for the 'Color' linespec property of plot. So you could maybe use a function like this:
function h = plot_colors(X, lineCount, varargin)
%// For more control - move these four lines outside of the function and make replace lineCount as a parameter with lineColors
t = linspace(0,1,lineCount)'; %//'
s = 1/2 + zeros(lineCount,1);
v = 0.8*ones(lineCount,1);
lineColors = colormap(squeeze(hsv2rgb(t,s,v)));
for row = 1:size(X,1)
h = plot(X(row, :), 'Color', lineColors(row,:), varargin{:}); %// Assuming I've remembered how to use it correctly, varargin should mean you can still pass in all the normal plot parameters like line width and '-' etc
hold on;
end
end
where lineCount is the largest number of lines amongst your x matrices
If you want a slightly hacky, minimal lines-of-code approach perhaps you could plot an appropriate number of (0,0) dots at the end of each matrix plot to nudge your colourorder back to the beginning - it's like Mohsen Nosratinia's solution but less elegant...
Assuming there are seven colours to cycle through like in matlab you could do something like this
% number of colours in ColorOrder
nco = 7;
% plot matrix 1
plot(x1');
% work out how many empty plots are needed and plot them
nep = nco - mod(size(x1,1), nco); plot(zeros(nep,nep));
% plot matrix 2
plot(x2');
...
% cover up the coloured dots with a black one at the end
plot(0,0,'k');
I have a Matlab figure with two histograms on it
,
created with hist() function. Now I want to add two plots in the same figure (bell distribution actually:
,
but they have different scale. I thought I could use plotyy, but I already have my first plot-scale on the figure. How can I add the second plot-scale?
Generally, this is one way to do it:
%// example data
rng(0,'twister')
data = randn(1000,3);
x = linspace(-4,4,100);
y = 16 - x.^2;
%// generate two axes at same position
ax1 = axes;
ax2 = axes('Position', get(ax1, 'Position'),'Color','none');
%// move second axis to the right, remove x-ticks and labels
set(ax2,'YAxisLocation','right')
set(ax2,'XTick',[])
%// plot hist and line plot
hist(ax1,data); hold on
plot(ax2,x,y)
ylabel(ax1,'label of hist')
ylabel(ax2,'label of plot')
xlabel(ax1,'Hello World!')
I know how to create the Bode plots with bode() function. If I want to overlap two or more systems frequency responses, I use
bode(sys1,sys2,...)
or
hold on
When I want to reach the plot in order to put a legend with text(), for instance, is easy to reach the second plot. Something like the figure pointer always returns to the second plot (phase graph).
i.e., if try these lines:
G = tf([1],[1 6]); figure(1); bode(G); text(10,-20,'text');
G = tf([1],[1 6]); figure(2); bode(G); text(10,-20,'text');
when I return to the first figure, with figure(1), and try
figure(1); text(10,-20,'text')
legend is displayed in the second plot (Phase plot)
I try these other lines:
P = bodeoptions; % Set phase visiblity to off
P.PhaseVisible = 'off';
G = tf([1],[1 6]);
figure(1); bode(G,P); text(10,-20,'text');
figure(1); text(10,-20,'text');
As you can see, even I turn off the phase plot visiblity, the legend is not displayed.
Essentialy, my question is, how do I reach first and second plots, one by one? I tried with subplot(), but it is pretty clear this is not the way Matlab traces these plots.
Thanks in advance.
It all comes to getting into upper plot, since after bodeplot command the lower one is active. Intuitively one would want to call subplot(2,1,1), but this just creates new blank plot on top of if. Therefore we should do something like this:
% First, define arbitrary transfer function G(s), domain ww
% and function we want to plot on magnitude plot.
s = tf('s');
G = 50 / ( s*(1.6*s+1)*(0.23*s+1) );
ww = logspace(0,3,5000);
y = 10.^(-2*log10(ww)+log10(150));
hand = figure; % create a handle to new figure
h = bodeplot(G,ww);
hold on;
children = get(hand, 'Children') % use this handle to obtain list of figure's children
% We see that children has 3 objects:
% 1) Context Menu 2) Axis object to Phase Plot 3) Axis object to Magnitude Plot
magChild = children(3); % Pick a handle to axes of magnitude in bode diagram.
% magChild = childern(2) % This way you can add data to Phase Plot.
axes(magChild) % Make those axes current
loglog(ww,y,'r');
legend('transfer function','added curve')
you can get magnitude and phase data separately for each system using:
[mag,phase] = bode(sys,w)
now you can use subplot or plot to plot the diagram you want.
The only solution I was able to perform is taking into account axis position. It is not very clean but it works.
Here is the code to select mag plot:
ejes=findobj(get(gcf,'children'),'Type','axes','visible','on');
posicion=get(ejes,'pos');
tam=length(posicion);
for ii=1:tam
a=posicion{ii}(2);
vectorPos(ii)=a;
end
[valorMax,ind]=max(vectorPos); % min for choosing the phase plot
axes(ejes(ind))