How to make previous inputs progressively fade out in a Matlab plot when I add new inputs - matlab

Let's say I have this very simple loop
for i=1:10
[xO, yO, xA, yA, xB, yB, xC, yC] = DoSomething(i);
line([xO,xA,xB,xC],[yO,yA,yB,yC]);
pause(0.1);
end
The coordinates that I am plotting correspond to the joints of a multibody system, and I am simulating their positions over time (please see a sample of the plot here):
Since some of the links move in a periodic way, it gets confusing to keep track visually of the movement. For this reason, now comes the question: how can I plot the lines in a way that, when a new line is plotted, the previous lines are faded progressively? In other words, so that I have a gradient from the most recently plotted data (most opaque) to the oldest data (increasingly transparent until it completely fades out).
This way when a new line is drawn in the same position as very old data, I will notice that it is a new one.

You can do this by modifying the 4th Color attribute of past lines.
Here's a demo resulting gif, where I faded out 10% of the transparency each frame, so only the most recent 10 lines are visible.
Here is the code, see my comments for details:
% Set up some demo values for plotting around a circle
a = 0:0.1:2*pi; n = numel(a);
[x,y] = pol2cart( a, ones(1,n) );
% Initialise the figure, set up axes etc
f = figure(1); clf; xlim([-1,1]); ylim([-1,1]);
% Array of graphics objects to store the lines. Could use a cell array.
lines = gobjects( 1, n );
% "Buffer" size, number of historic lines to keep, and governs the
% corresponding fade increments.
nFade = 10;
% Main plotting loop
for ii = 1:n
% Plot the line
lines(ii) = line( [0,x(ii)], [0,y(ii)] );
% Loop over past lines.
% Note that we only need to go back as far as ii-nFade, earlier lines
% will already by transparent with this method!
for ip = max(1,ii-nFade):ii
% Set the 4th Color attribute value (the alpha) as a percentage
% from the current index. Could do this various ways.
lines(ip).Color(4) = max( 0, 1 - (ii-ip)/nFade );
end
% Delay for animation
pause(0.1);
end
You may want to do some plot/memory management if you've got many lines. You can delete transparent lines by adding something like
if lines(ii).Color(4) < 0.01
delete(lines(ii));
end
Within the loop. This way your figure won't have loads of transparent remnants.
Notes:
I generated the actual gif using imwrite in case that's of interest too.
Apparently the 4th Color value 'feature' has been depreciated in R2018b (not sure it was ever officially documented).
Got enough upvotes to motivate making a slightly more fun demo...

Solution for Matlab 2018a or later (or earlier, later than 2012a at least)
Since the fourth color parameter as alpha value is no longer supported in Matlab 2018a (and apparently was never supposed to as Cris Luengo pointed out), here a solution that works in Matlab 2018a using the patchline function from the file exchange (credits to Brett Shoelson).
% init the figure
figure(); axes();
hold on; xlim([-1 0.5]); ylim([0 1]);
% set fraction of alpha value to take
alpha_fraction = 0.7;
n_iterations = 200;
% looping variable to prevent deleting and calling already deleted lines
% i.e. to keep track of which lines are already deleted
delete_from = 1;
for i=1:n_iterations
% your x, y data
[x, y] = doSomething(i);
% create line with transparency using patchline
p(i) = patchline(x,y, 'linewidth', 1, 'edgecolor', 'k');
% set alpha of line to fraction of previous alpha value
% only do when first line is already plotted
if i > 1
% loop over all the previous created lines up till this iteration
% when it still exists (delete from that index)
for j = delete_from:i-1
% Update the alpha to be a fraction of the previous alpha value
p(j).EdgeAlpha = p(j).EdgeAlpha*alpha_fraction;
% delete barely visible lines
if p(j).EdgeAlpha < 0.01 && delete_from > j
delete(p(j));
% exclude deleted line from loop, so edgealpha is not
% called again
delete_from = j;
end
end
end
% pause and behold your mechanism
pause(0.1);
end
I included the deletion of barely visible lines, as suggested by #Wolfie (my own, perhaps less elegant implementation)
And here a demonstration of a quick release mechanism:

I'm adding a 2nd answer to clearly separate two completely different approaches. My 1st answer uses the undocumented (and as of 2018b, depreciated) transparency option for lines.
This answer offers a different approach for line drawing which has no compatibility issues (these two 'features' could be implemented independently):
Create a fixed n lines and update their position, rather than creating a growing number of lines.
Recolour the lines, fading to white, rather than changing transparency.
Here is the code, see comments for details:
% "Buffer" size, number of historic lines to keep, and governs the
% corresponding fade increments.
nFade = 100;
% Set up some demo values for plotting around a circle
dt = 0.05; a = 0:dt:2*pi+(dt*nFade); n = numel(a); b = a.*4;
[x1,y1] = pol2cart( a, ones(1,n) ); [x2,y2] = pol2cart( b, 0.4*ones(1,n) );
x = [zeros(1,n); x1; x1+x2]; y = [zeros(1,n); y1; y1+y2];
% Initialise the figure, set up axes etc
f = figure(1); clf; xlim([-1.5,1.5]); ylim([-1.5,1.5]);
% Draw all of the lines, initially not showing because NaN vs NaN
lines = arrayfun( #(x)line(NaN,NaN), 1:nFade, 'uni', 0 );
% Set up shorthand for recolouring all the lines
recolour = #(lines) arrayfun( #(x) set( lines{x},'Color',ones(1,3)*(x/nFade) ), 1:nFade );
for ii = 1:n
% Shift the lines around so newest is at the start
lines = [ lines(end), lines(1:end-1) ];
% Overwrite x/y data for oldest line to be newest line
set( lines{1}, 'XData', x(:,ii), 'YData', y(:,ii) );
% Update all colours
recolour( lines );
% Pause for animation
pause(0.01);
end
Result:

Related

Although I used 'drawnow' and 'hold on', last plot still appears in animation - MATLAB

I read a lot of answers here, but for some reason my animation still doesn't work as expected.
The axis range should vary from frame to frame. The 'Hurricane Center' caption should remain in the center all the time, but the captions from the previous frames must be erased. Also, I'm afraid that some of the data from previous parts remain.
I used hold on and draw now but it still happens.
The animation can be seen here:
Code:
v = VideoWriter('test_video.avi');
v.FrameRate = 4;
v.open()
hold on
for i=1:length(relevant(1,1,:))
if isempty(relevant) == 0
title('Lightning around Hurricane Jerry')
grid on
ylim([Interp_Jerry(i,2)-Radius Interp_Jerry(i,2)+Radius])
xlim([Interp_Jerry(i,3)-Radius Interp_Jerry(i,3)+Radius])
ylabel('latitude')
xlabel('longitude')
text(Interp_Jerry(i,3),Interp_Jerry(i,2),txt1);
scatter(relevant(:,3,i),relevant(:,2,i),'.');
drawnow
pause(0.1);
v.writeVideo(getframe(fig));
end
end
v.close()
The best of the two worlds:
v = VideoWriter('test_video.avi');
v.FrameRate = 4;
v.open()
hold on;
for i=1:length(relevant(1,1,:))
if ~isempty(relevant) % Corrected
if i == 1
% Prepare first plot and save handles of graphical objects
ht = text(Interp_Jerry(i,3),Interp_Jerry(i,2),txt1);
hold on;
hs = scatter(relevant(:,3,i),relevant(:,2,i),'.');
ylabel('latitude')
xlabel('longitude')
title('Lightning around Hurricane Jerry')
grid on
else
% Update graphical objects
set(ht, 'position', [Interp_Jerry(i,3), Interp_Jerry(i,2)]);
set(hs, 'XData', relevant(:,3,i) , 'YData' , relevant(:,2,i));
end
ylim([Interp_Jerry(i,2)-Radius Interp_Jerry(i,2)+Radius])
xlim([Interp_Jerry(i,3)-Radius Interp_Jerry(i,3)+Radius])
drawnow
pause(0.1);
v.writeVideo(getframe(fig));
end
end
v.close()
Instead of writing the text every time, just modify its position in the loop. Create a text object out side of the loop
t = text(position1, position2, txt);
in the loop change the position and if necessary the text
set(t, 'position', [new_position1, new_position2]);
If you don't want the previous data to remain, then you shouldn't use hold on... I think you should revise your code as follows:
v = VideoWriter('test_video.avi');
v.FrameRate = 4;
v.open();
fg = figure();
% Do not hold on, so that data is not retained frame-to-frame
for i=1:length(relevant(1,1,:))
% You don't need to test if 'relevant' is empty, since you're looping to its length!
% New plot
scatter(relevant(:,3,i),relevant(:,2,i),'.');
% Customise plot (labels / axes / text / ...)
title('Lightning around Hurricane Jerry')
ylabel('latitude')
xlabel('longitude')
ylim([Interp_Jerry(i,2)-Radius Interp_Jerry(i,2)+Radius]);
xlim([Interp_Jerry(i,3)-Radius Interp_Jerry(i,3)+Radius]);
text(Interp_Jerry(i,3),Interp_Jerry(i,2),txt1);
grid on;
drawnow;
% You don't need to pause whilst plotting, you already set the video framerate.
% pause(0.1);
v.writeVideo(getframe(fg));
end
v.close()

Adding colors to lines of a stairstep plot

I am trying to plot a hypnogram (graph that shows sleep cycles) and am currently using stairstep function to plot it. Below is a sample data since the one I am working with is huge:
X = linspace(0,4*pi,10);
Y = sin(X);
stairs(X,Y)
How do I make the lines of every ticks/score on the y-axis have a unique color? Which looks something like this:
One way to do it would be to segregate your data into as many dataset as your have flat levels, then plot all these data sets with the required properties.
There is however a way to keep the original dataset into one piece. If we consider your initial example data:
X = linspace(0,4*pi,10);
Y = sin(X);
step 1: recreate a "stair" like data set
Then by recombining the elements of X and Y we can obtain the exact same output than with the stairs function:
x = reshape( [X;X], 1,[] ); x(1) = [] ; % duplicate each element, remove the first one
y = reshape( [Y;Y], 1,[] ); y(end) = [] ; % duplicate each element, remove the lastone
hp = plot(x,y) ;
step 2: Use patch to be able to specify level colors
The patch object has many option for colouring faces, vertex and edges. The default patch object will try to close any profile given in coordinate by joining the first and last point. To override this behaviour, you just need to add a NaN element to the end of the coordinate set and patch will produce a simple line (but all the colouring options remain !).
To determine how many levels and how many colors we will need, we use the function unique. This will tell us how many unique levels exist in the data, and also we can associate each level with an index which will point to the color map.
%% Basic level colored line patch
% create profile for patch object
x = reshape([X;X],1,[]); x(1) = [] ; % same as above to get a "stairs" shape
y = reshape([Y;Y],1,[]); y(end) = [] ; % idem
xp = [x,NaN] ; % add NaN in last position so the patch does not close the profile
yp = [y,NaN]; % idem
% prepare colour informations
[uy,~,colidx] = unique(Y) ;
ncolor = length(uy) ; % Number of unique level
colormap(hsv(ncolor)) % assign a colormap with this number of color
% create the color matrix wich will be sent to the patch object
% same method of interleaving than for the X and Y coordinates
cd = reshape([colidx.';colidx.'],1,[]);
hp = patch(xp,yp,cd,'EdgeColor','interp','LineWidth',2) ;
colorbar
Yes! ... now our flat levels have a colour corresponding to them ... but wait, those pesky vertical lines are still there and polluting the graph. Could we colour them in a different way? Unfortunately no. No worries however, there is still a way to make them completely disappear ...
step 3: Use NaN to disable some segments
Those NaN will come to the rescue again. Any segment defined with a NaN will not be plotted by graphic functions (be it plot, patch, surf or any other ...). So what we can do is again interleave some NaN in the original coordinate set so only the horizontal lines will be rendered. Once the patch is created, we can build a second, "opposite", coordinate set where only the vertical lines are visible. For this second set, since we do not need fancy colouring, we can simply render them with plot (but you could also build a specific patch for that too if you wanted to colour them differently).
%% invisible vertical line patch + dashed vertical lines
% prepare profile points, interleaving NaN between each pair
vnan = NaN(size(X)) ;
xp = reshape([X;vnan;X],1,[]); xp([1:2 end]) = [] ;
yp = reshape([Y;Y;vnan],1,[]); yp(end-2:end) = [] ;
% prepare the vertical lines, same method but we interleave the NaN at one
% element offset
xv = reshape([X;X;vnan],1,[]); xv([1:3 end]) = [] ;
yv = reshape([Y;vnan;Y],1,[]); yv([1:2 end-1:end]) = [] ;
% prepare colormap and color matrix (same method than above)
[uy,~,colidx] = unique(Y) ;
ncolor = length(uy) ; % Number of unique level
colormap(hsv(ncolor)) % assign a colormap with this number of color
% create the color matrix wich will be sent to the patch object
% same method of interleaving than for the X and Y coordinates
cd = reshape([colidx.';colidx.';vnan],1,[]); cd(end-2:end) = [] ;
% draw the patch (without vertical lines)
hp = patch(xp,yp,cd,'EdgeColor','flat','LineWidth',2) ;
% add the vertical dotted lines
hold on
hv = plot(xv,yv,':k') ;
% add a label centered colorbar
colorbar('Ticks',((1:ncolor)+.5)*ncolor/(ncolor+1),'TickLabels',sprintf('level %02d\n',1:ncolor))
I have used the hsv colormap in the last example because your example seems to indicate that you do not need gradually progressing colors. You could also define a custom colormap with the exact color you want for each level (but that would be another topic, already covered many time if you search for it on Stack Overflow).
Happy R.E.M. sleeping !
Below code is not that efficient, but works well.
Basically, it draws line by line from left to right.
Firstly, generate sample data
num_stage = 6;
% generate sample point
x = linspace(0,1,1000)';
% generate its stage
y = round((sin(pi*x)+1)*(num_stage-1)/2)/(num_stage-1);
stage = unique(y); % find value of each stage
color_sample = rand(num_stage,3); % set color sample
Then we can draw like this
idx = find([1;diff(y)]); % find stage change
idx(end+1) = length(x)+1; % add last point
% display routine
figure;
% left end stage
k = 1;
% find current stage level
c = find(stage == y(idx(k)));
% plot bold line
plot(x([idx(k),idx(k+1)-1]),y(idx(k))*ones(2,1),'color',color_sample(c,:),'linewidth',5);
hold on;
for k = 2 : length(idx)-1
% find current stage level
c = find(stage == y(idx(k)));
% plot dashed line from left stage to current stage
plot(x([idx(k)-1,idx(k)]),[y(idx(k-1));y(idx(k))],'--','color',[0.7,0.7,0.7]);
% plot bold line for current stage with specified color
plot(x([idx(k),idx(k+1)-1]),y(idx(k))*ones(2,1),'color',color_sample(c,:),'linewidth',5);
end
% set x-axis
set(gca,'xlim',[x(1),x(end)]);
Following is result
Use if statement and divide it blocks. Check the criteria of Y-axis to be in a certain range and if it falls in that range, plot it there using the colors you want. For example if (y>1) plot(x,y,'r') else if (y some range) plot(x,y,'b'). Hope it helps

Separating axes from plot area in MATLAB

I find that data points that lie on or near the axes are difficult to see. The obvious fix, of course, is to simply change the plot area using axis([xmin xmax ymin ymax]), but this is not preferable in all cases; for example, if the x axis is time, then moving the minimum x value to -1 to show activity at 0 does not make sense.
Instead, I was hoping to simply move the x and y axes away from the plot area, like I have done here:
left: MATLAB generated, right: desired (image editing software)
Is there a way to automatically do this in MATLAB? I thought there might be a way to do it by using the outerposition axes property (i.e., set it to [0 0 0.9 0.9] and drawing new axes where they originally were?), but I didn't get anywhere with that strategy.
The answers here already show you most of the way - here is the last step to separate the x and y axle as per the example you put together.
f = figure ( 'color', 'white' );
% create the axes and set some properties
ax = axes ( 'parent', f, 'box', 'off', 'nextplot', 'add', 'XMinorTick', 'on', 'YMinorTick', 'on' );
% plot some data
plot ( ax, 0:10, [0:10].^2, 'rx-' )
% modify the x and y limits to below the data (by a small amount)
ax.XLim(1) = ax.XLim(1)-(ax.XTick(2)-ax.XTick(1))/4;
ax.YLim(1) = ax.YLim(1)-(ax.YTick(2)-ax.YTick(1))/4;
% Set the tick direction
ax.TickDir = 'out';
% draw the plot to generate the undocumented vertex data var
drawnow()
%% R2015a
% X, Y and Z row of the start and end of the individual axle.
ax.XRuler.Axle.VertexData(1,1) = 0;
ax.YRuler.Axle.VertexData(2,1) = 0;
%% R2015b
% extract the x axis vertext data
% X, Y and Z row of the start and end of the individual axle.
vd = get(ax.XAxis.Axle,'VertexData');
% reset the zero value
vd(1,1) = 0;
% Update the vertex data
set(ax.XAxis.Axle,'VertexData',vd);
% repeat for Y (set 2nd row)
vd = get(ax.YAxis.Axle,'VertexData');
vd(2,1) = 0;
set(ax.YAxis.Axle,'VertexData',vd);
Edit: The vertex is something that Matlab recreates whenever the axes/figure changes size or if you zoom or pan for example.
You can try to counteract this (remember you are using undocumented features here) by adding a listener to attempt to capture this. We can use the MarkedClean event which is called quite a lot of times.
addlistener ( ax, 'MarkedClean', #(obj,event)resetVertex(ax) );
Where you resetVertex function is something like: (R2015b shown only)
Edit 2 added the code to turn off the minor ticks below 0.
function resetVertex ( ax )
% extract the x axis vertext data
% X, Y and Z row of the start and end of the individual axle.
ax.XAxis.Axle.VertexData(1,1) = 0;
% repeat for Y (set 2nd row)
ax.YAxis.Axle.VertexData(2,1) = 0;
% You can modify the minor Tick values by modifying the vertex data
% for them, e.g. remove any minor ticks below 0
ax.XAxis.MinorTickChild.VertexData(:,ax.XAxis.MinorTickChild.VertexData(1,:)<0) = [];
ax.YAxis.MinorTickChild.VertexData(:,ax.YAxis.MinorTickChild.VertexData(2,:)<0) = [];
end
Note: this uses undocumented features -> so may only work in certain versions of Matlab (I have added the code for r2015a & r2015b) and Matlab may recreate the vertex data depending on what you do with the plots..
Here is a simple way for achieving that:
% some data:
x = 1:100;
f=#(x) 5.*x;
y=f(x)+rand(1,length(x))*50;
close all
% plotting:
f1 = figure('Color','white');
ax = axes;
plot(ax,x,y,'o');
% 'clean' the data area a little bit:
box off
ax.TickDir = 'out';
% pushing the axis a bit forward:
lims = axis;
pos = ax.Position;
axis([lims(1)-ax.XTick(2)/5 lims(2)+0.1 lims(3)-ax.YTick(2)/5 lims(4)+0.1])
% Create lines
firstXtick = 0.013; %this value need to be adjusted only once per figure
firstYtick = 0.023; %this value need to be adjusted only once per figure
lx = annotation(f1,'line',[pos(1) pos(1)+firstXtick],...
[pos(2) pos(2)],'Color',[1 1 1],'LineWidth',1);
ly = annotation(f1,'line',[pos(1) pos(1)],...
[pos(2) pos(2)+firstYtick],'Color',[1 1 1],'LineWidth',1);
Which yields this figure:
The only thing to adjust here, once per type of figure, is firstXtick and firstYtick values, that have to be fine tuned to the specific axis. After setting them to the correct value the figure can be resized with no problem. Zoom and pan require a little fixes.
You can start your axes from less than zero and then remove the less than zero ticks from your plot. e.g.
plot(0:3:30,0:3:30); %Some random data for plotting
h = gca;
axis([-1 30 -1 30]); %Setting the axis from less than zero
box off; %Removing box
h.TickDir = 'out'; %Setting Direction of ticks to outwards
h.XTickLabel(1)= {' '}; %Removing the first tick of X-axis
h.YTickLabel(1)= {' '}; %Removing the first tick of Y-axis
With this code, you'll get this result:
This may have a drawback, sometimes, that zero ticks may also get removed (as you can see in above figure). This is because the plot had set the first ticks of axes equal to zero. This can be avoided using if condition. So, the code can be modified as below:
plot(0:3:30,0:3:30);
h = gca;
axis([-1 30 -1 30]);
box off;
h.TickDir = 'out';
if str2num(cell2mat(h.XTickLabel(1))) <0
h.XTickLabel(1)= {' '};
end
if str2num(cell2mat(h.YTickLabel(1))) <0
h.YTickLabel(1)= {' '};
end
The above code will yield the following result:-
Also note that, for your case, since your axes ticks are very less, -1 may not be much suitable for the starting value of axes and you may need to use -0.1 instead i.e. axis([-0.1 30 -0.1 30]);
With a slight modification of #matlabgui's answer you can track the (major) tick limits:
ax = gca();
% Set the tick direction
ax.TickDir = 'out';
% Make sure this stays when saving, zooming, etc
addlistener ( ax, 'MarkedClean', #(obj,event) change_ticks(ax) );
% Draw the plot to generate the undocumented vertex data variable
% and call callback for the first time
drawnow();
The callback
function change_ticks( ax )
% Modify ruler
ax.XRuler.Axle.VertexData(1,1) = ax.XTick(1);
ax.XRuler.Axle.VertexData(1,2) = ax.XTick(end);
ax.YRuler.Axle.VertexData(2,1) = ax.YTick(1);
ax.YRuler.Axle.VertexData(2,2) = ax.YTick(end);
end
I haven't test extensively but seems to work for custom ticks too. This nicely cuts the rulers not only on zero but beyond the fist and last tick. This was tested in Matlab 2019a on Windows and ax.XRuler.Axle.VertexData works just fine. Note this is only for major ticks!

In MATLAB: How can XData and YData be updated with a changing number of lines?

I am looking for a way to add vertical dividing lines separating consecutive days in a dynamically updating plot of animal migration data (location vs. time). Part of the challenge is that the number of these dividers changes as the plot domain expands to display more temporal data: As the number of days in the plot increases from 3 to 5, for example, the number of dividers increases by 2.
A minimal code example, written in MATLAB, is shown below:
xcols = [1; 1];
ycols = [0; 1];
figure(4)
clf
h.divs = plot(xcols,ycols,':k');
xlabel('time')
ylabel('location')
for ii=2:6
xcols(:,end+1) = [ii; ii];
ycols(:,end+1) = [0; 1];
% set(h.divs, 'XData', xcols, 'YData', ycols);
% set(h.divs, {'XData'}, num2cell(xcols',2), {'YData'}, num2cell(ycols',2));
drawnow
pause(1)
end
The problem centers on the two lines that have been commented out. If I comment in the first of these to try to update XData and YData with each new set of dividers (given as the 2 x DividerCount matrices xcols and ycols), then I receive an error that these inputs "must be a vector of numeric type". If I instead comment in the second line as way of using cell arrays to get around this (per this Stack Overflow post and this MATLAB Newsgroup post), then the code returns an error that "cell array handle dimension must match handle vector length" as soon as the number of dividers changes.
Hacky solutions are certainly possible. For example, the dividers can be plotted as a single line of horizontal and vertical segments, where the horizontal segments are placed above and below the y-axis limits of the plot. Or a fixed number of dividers can be used, with some of the dividers plotted outside the x-axis limits of the plot. The question is whether there is a non-hacky approach – one that can plot a potentially changing number of lines of identical style in the same figure with each pass of the loop.
Assume we have at the beginning
xcols = [1:3; 1:3];
ycols = [0 0 0; 1 1 1];
then h.divs = plot(xcols,ycols,':k'); will create 3 line objects.
Using
set(h.divs,{'XData'},num2cell(xcols',2),{'YData'},num2cell(ycols',2));
with size(xcols, 2)>3 will fail, because this assumes there are more than 3 graphics objects to set values for (but numel(h.divs) is still 3).
So do we have to create a new plot for every divider?
No!, because if we insert NaNs into our data, we can introduce gaps into lines.
As a first iteration, we could use this:
xcols = [1 1];
ycols = [0 1];
figure(4)
clf
h.divs = plot(xcols,ycols,':k');
for ii=2:6
xcols(end+(1:3)) = [nan ii ii];
ycols(end+(1:3)) = [nan 0 1];
set(h.divs, 'XData', xcols, 'YData', ycols);
drawnow
pause(1)
end
Starting with one divider which we plot, we then grow the data vectors (one-dimensional!) with a new value pair separated from the old data by a nan.
This of course grows the data vectors in the loop, which is not so great. Instead, if we know how many dividers there will be, we can preallocate with NaNs and only fill in new data in the loop:
n_div = 6;
xcols = nan(3 * n_div, 1);
ycols = nan(3 * n_div, 1);
figure(4)
clf
h.divs = plot(xcols,ycols,':k');
for ii=1:6
xcols((ii - 1)*3 + (1:2)) = [ii ii];
ycols((ii - 1)*3 + (1:2)) = [0 1];
set(h.divs, 'XData', xcols, 'YData', ycols);
drawnow
pause(1)
end
This has also the benefit that we can assign XData and YData separately, as in the new handle syntax:
h.divs.XData = xcols;
h.divs.YData = cols;
(or even better: h.divs.XData((ii - 1)*3 + (1:2)) = [ii ii];), because the lengths don't change.
You can start with divider definition:
divider.x=[];
divider.y=[];
divider.counter=0;
h.div=line('xdata',divider.x,'ydata',divider.y,'linestyle',':','color','k');
Which will draw no line, but handle will be set.
Then, perhaps in some loop, you can call:
divider.counter=divider.counter+1; % increase the counter
divider.x=[divider.x,nan,divider.counter*[1 1]]; % append X coords of new divider line
divider.y=[divider.y,nan,divider.counter*[0 1]]; % append Y coords of new divider line
set(h.div,'xdata',divider.x,'ydata',divider.y) % update dividers
drawnow % update figure immediately
This approach works because NaN value can be passed to line function but will not be plotted and neither will be lines from neighbour points.

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