Customizing multiple rootlocus plot colors (scale of grey) Matlab - matlab

I would like to customize the color of my rootlocus plot.
I use a for cycle to plot 10 rootlocus (with slightly different systems in the loop) and I would like every of them to be of a different shade of grey. I thought to use the gray command to obtain a matrix to store the RGB data and then use this matrix in the rlocus(sys,K,'style') command (choosing the i-th line at the i-th iteration of my cycle). Unfortunately the command requires the style to be a cell (for example 'g' or 'b') and not a vector of numbers.
This is a sample of my code:
figure()
hold on
L = [sys1, sys2, ..., sys10];
colors = gray(10);
for i = 0:9
rlocus (L(i+1), 'Color', colors(i+1, :));
end

The rlocus() function is not as powerful as the plot() function and only has limited support for setting colours with rlocus(sys, 'b') as you've noticed. However, we can combine it with the plot() function to make use of its power.
Here I use [R, K] = rlocus(sys) to return the values of the root locus, R. Each row of R represents a different trajectory. We can plot 1 trajectory of the root locus with plot(R(m, :)) and utilise the strength of plot() to change the colour however we wish.
L = [sys1, sys2, sys3, sys4, sys5, sys6, sys7, sys8, sys9, sys10];
C = gray(numel(L) + 1); % Extra 1 because the last value will be
% white and plotting white on white does
% not look well :P
figure;
hold on
for n = 1:numel(L)
[R, K] = rlocus(L(n));
for m = 1:numel(R)/length(R)
plot(R(m, :), 'Color', C(n, :));
end
end
hold off

Related

Color-coded representation of data in a 2-D plot (in MATLAB)

I have several 4 x 4 matrices with data that I would like to represent in a 2-D plot. The plot is supposed to show how the results of a simulation change with varying parameters.
On the y-axis I would like to have the possible values of parameter A (in this case, [10,20,30,40]) and on the x-axis I want to have the possible values of parameter B (in this case, [2,3,4,5]). C is a 4 x 4 matrix with the evaluation value for running the simulation with the corresponding parameter combination.
Example: The evaluation value for the parameter combination A = 10, B = 2 equals 12 dB. I would like to plot it at the cross section A and B (I hope you understand what I mean by this) and code the value by a fat colored dot (e.g. red means high values, blue means low values).
How can I do this? I would basically like to have something like mesh without lines.
I'm sorry for my imperfect English! I hope you understood what I would like to achieve, thank you in advance!
You can do this with the mesh command (and the built-in colormaps you can choose from can be found here, or you could even make your own):
[A, B] = meshgrid(10:10:40, 2:5); % Grids of parameter values
C = rand(4); % Random sample data
hMesh = mesh(A, B, C); % Plot a mesh
set(hMesh, 'Marker', '.', ... % Circular marker
'MarkerSize', 60, ... % Make marker bigger
'FaceColor', 'none', ... % Don't color the faces
'LineStyle', 'none'); % Don't render lines
colormap(jet); % Change the color map
view(0, 90); % Change the view to look from above
axis([5 45 1.5 5.5]); % Expand the axes limits a bit
colorbar; % Add colorbar
And here's the plot:

Matlab: 1D array to RGB triplets with colormap

I'm trying to draw a set of rectangles, each with a fill color representing some value between 0 and 1. Ideally, I would like to use any standard colormap.
Note that the rectangles are not placed in a nice grid, so using imagesc, surf, or similar seems unpractical. Also, the scatter function does not seem to allow me to assign a custom marker shape. Hence, I'm stuck to plotting a bunch of Rectangles in a for-loop and assigning a FillColor by hand.
What's the most efficient way to compute RGB triplets from the scalar values? I've been unable to find a function along the lines of [r,g,b] = val2rgb(value,colormap). Right now, I've built a function which computes 'jet' values, after inspecting rgbplot(jet). This seems a bit silly. I could, of course, obtain values from an arbitrary colormap by interpolation, but this would be slow for large datasets.
So, what would an efficient [r,g,b] = val2rgb(value,colormap) look like?
You have another way to handle it: Draw your rectangles using patch or fill specifying the color scale value, C, as the third parameter. Then you can add and adjust the colorbar:
x = [1,3,3,1,1];
y = [1,1,2,2,1];
figure
for ii = 1:10
patch(x + 4 * rand(1), y + 2 * rand(1), rand(1), 'EdgeColor', 'none')
end
colorbar
With this output:
I think erfan's patch solution is much more elegant and flexible than my rectangle approach.
Anyway, for those who seek to convert scalars to RGB triplets, I'll add my final thoughts on the issue. My approach to the problem was wrong: colors should be drawn from the closest match in the colormap without interpolation. The solution becomes trivial; I've added some code for those who stumble upon this issue in the future.
% generate some data
x = randn(1,1000);
% pick a range of values that should map to full color scale
c_range = [-1 1];
% pick a colormap
colormap('jet');
% get colormap data
cmap = colormap;
% get the number of rows in the colormap
cmap_size = size(cmap,1);
% translate x values to colormap indices
x_index = ceil( (x - c_range(1)) .* cmap_size ./ (c_range(2) - c_range(1)) );
% limit indices to array bounds
x_index = max(x_index,1);
x_index = min(x_index,cmap_size);
% read rgb values from colormap
x_rgb = cmap(x_index,:);
% plot rgb breakdown of x values; this should fall onto rgbplot(colormap)
hold on;
plot(x,x_rgb(:,1),'ro');
plot(x,x_rgb(:,2),'go');
plot(x,x_rgb(:,3),'bo');
axis([c_range 0 1]);
xlabel('Value');
ylabel('RGB component');
With the following result:

Reset ColorOrder index for plotting in Matlab / Octave

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');

matlab plotting a family of functions

Generate a plot showing the graphs of
y=(2*a+1)*exp(-x)-(a+1)*exp(2*x)
in the range x ∈ <-2, 4> for all integer values of a between -3 and 3
I know how to make typical plot for 2 values and set a range on the axes, but how to draw the graph dependent on the parameter a?
To elaborate on Ben Voigt's comment: A more advanced technique would be to replace the for-loop with a call to bsxfun to generate a matrix of evaluations of M(i,j) = f(x(i),a(j)) and call plot with this matrix. Matlab will then use the columns of the matrix and plot each column with individual colors.
%%// Create a function handle of your function
f = #(x,a) (2*a+1)*exp(-x)-(a+1)*exp(2*x);
%%// Plot the data
x = linspace(-2, 4);
as = -3:3;
plot(x, bsxfun(f,x(:),as));
%%// Add a legend
legendTexts = arrayfun(#(a) sprintf('a == %d', a), as, 'uni', 0);
legend(legendTexts, 'Location', 'best');
You could also create the evaluation matrix using ndgrid, which explicitly returns all combinations of the values of x and as. Here you have to pay closer attention on properly vectorizing the code. (We were lucky that the bsxfun approach worked without having to change the original f.)
f = #(x,a) (2*a+1).*exp(-x)-(a+1).*exp(2*x); %// Note the added dots.
[X,As] = ndgrid(x,as);
plot(x, f(X,As))
However for starters, you should get familiar with loops.
You can do it using a simple for loop as follows. You basically loop through each value of a and plot the corresponding y function.
clear
clc
close all
x = -2:4;
%// Define a
a = -3:3;
%// Counter for legend
p = 1;
LegendText = cell(1,numel(a));
figure;
hold on %// Important to keep all the lines on the same plot.
for k = a
CurrColor = rand(1,3);
y= (2*k+1).*exp(-x)-(k+1).*exp(2.*x);
plot(x,y,'Color',CurrColor);
%// Text for legend
LegendText{p} = sprintf('a equals %d',k);
p = p+1;
end
legend(LegendText,'Location','best')
Which gives something like this:
You can customize the graph as you like. Hope that helps get you started!

Matlab: Set shading of single surface

I'm making a function which generalizes the cylinder function so that the cylinder has caps, can be any size and orientation. However on the look of the cylinder I am running into a jam. To get the caps to look right the curved part needs one set of shading and the caps need another. (And before you ask making 3 surfaces is not an option)
Here is the relevant code:
surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');
and in case you want to see the whole code.
Thank you for your help,
John
function varargout = DrawCylinder(x,y,z,r,h,aVec,bVec,cVec,ccolor, npts)
% DrawCylinder Generate a three-dimensional cylinder
%
% DrawCylinder(x,y,z,a,b,c,aVec,bVec,CVec,ccolor, npts)
% creates a surface plot of a cylinder whose center is at (x,y,z), has
% semiaxes of length a, b, and c. The unit vectors associated with each
% semixis are aVec, bVec, and cVec and must be size 3 x 1 (column vector)
% with size of npts + 1.
%
% H = DrawCylinder(...) creates the surface plot and returns the handle H to each
% graphical object created.
%
% [X Y Z] = DrawCylinder(...) does not generate the surface plot and returns
% the data necessary to create the surface using:
% SURF(X,Y,Z);
%
% [X Y Z C] = DrawCylinder(...) does not generate the surface plot and returns
% the data necessary to create the surface using:
% SURF(X,Y,Z,C,'cdataMapping','direct');
%CREATE SURFACE FOR CYLINDER
[xCyl,yCyl,zCyl]=cylinder(1,npts);
xSurf=[zeros(1,max(size(xCyl)));xCyl;zeros(1,max(size(xCyl)))];
ySurf=[zeros(1,max(size(yCyl)));yCyl;zeros(1,max(size(yCyl)))];
zSurf=[zeros(1,max(size(zCyl)));zCyl;ones(1,max(size(zCyl)))] - 0.5;
xSurf = xSurf*r;
ySurf = ySurf*r;
zSurf = zSurf*h;
%ROTATE CYLINDER
%Make sure aVec,bVec, and cVec are column unit vectors:
if all(size(aVec)==[1,3])
aVec=aVec';
end
if all(size(bVec)==[1,3])
bVec=bVec';
end
if all(size(cVec)==[1,3])
cVec=cVec';
end
aVec=aVec/norm(aVec); %Make unit vectors
bVec=bVec/norm(bVec);
cVec=cVec/norm(cVec);
rot = [aVec,bVec,cVec]; %The rotation matrix
[iMax, jMax] = size(xSurf);
for i=1:iMax
for j=1:jMax
rotatedPt = rot*[xSurf(i,j);ySurf(i,j);zSurf(i,j)];
xSurf(i,j) = rotatedPt(1);
ySurf(i,j) = rotatedPt(2);
zSurf(i,j) = rotatedPt(3);
end
end
%TRANSLATE CYLINDER
xSurf = xSurf + x;
ySurf = ySurf + y;
zSurf = zSurf + z;
c = ccolor*ones(size(xSurf));
if nargout == 0
surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');
elseif nargout == 1
varargout = {surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');};
elseif nargout == 3
varargout = {xSurf ySurf zSurf};
elseif nargout == 4
varargout = {xSurf ySurf zSurf c};
end
end
Edit 8/18/12:
Just so you can see.
This is what I am getting ...
And this is what I want ...
I'm pretty sure that by "shade" you simply mean the colors of the end caps and not a more complicated effect. If so that's pretty straightforward, I'll give an example in gray scale
Change
c = ccolor*ones(size(xSurf));
to
c = (ccolor/255)*ones(size(xSurf));
c([1 3],:)=max(0,(ccolor-10))/255;
the first line initializes the c matrix with a normalized ccolor (expecting an 8 bit greyscale ccolor input, it normalizes to 0..1). The second line changes the caps (rows 1 and 3) to be a slightly darker color bottoming out at 0 and leaves the cylinder surfaces (rows 2 and 4) alone.
In order to make sure you see the results correctly, you need to alter the nargout==0 condition so that it looks like this
surface(xSurf,ySurf,zSurf,c,'EdgeColor','none','FaceLighting','phong');
colormap(gray(256));
caxis([0 1]);
The colormap just sets the colormap, similar to an 8 bit gray scale. The caxis command is fairly critical. According to Matlab's surface documentation
MATLAB performs a linear transformation on this data to obtain colors from the current colormap
For our purposes that is bad. Since we only have two values the lowest would be changed to 0 and the highest to 1. That effectively ignores our ccolor input and gives a white cylinder with two black caps. Using caxis([0 1]) preserves the full scale and ccolor's position within it.
Update:
Sounds like I misunderstood what you wanted, the easiest way to achieve something very close to the effect you want is to set 'MeshStyle' to 'row', like this:
surface(xSurf,ySurf,zSurf,c,'EdgeColor','k','FaceLighting','phong','MeshStyle','row');
This will give you the following result :
There's still a central point, but it's by far the simplest way to produce that effect.