Producing subplots and then combine them into a figure later in MATLAB - matlab

My program produces small figures during the command cycle. Is there a way to just save these figures and then combine them in one figure later?

Consider the code:
hFig = figure;
%# create temporary subplots as template
for i=1:2, h(i) = subplot(2,1,i); end %# create subplots
pos = get(h, 'Position'); %# record their positions
delete(h) %# delete them
%# load the .fig files inside the new figure
fileNames = {'a.fig' 'b.fig'}; %# saved *.fig file names
for i=1:2
%# load fig
hFigFile = hgload( fileNames{i} );
%# move/copy axis from old fig to new fig
hAx = get(hFigFile, 'Child'); %# hAx = gca;
set(hAx, 'Parent',hFig)
%#hAx = copyobj(hAx,hFig);
%# resize it to match subplot position
set(hAx, 'Position',pos{i});
%# delete old fig
delete(hFigFile)
end
This was adapted from this newsgroup discussion

Use saveas. Save your subplot as a FIG file so you have complete control over it later (as opposed to a JPG).
Choose a tiling pattern and then use subplot to display multiple figures in one.

I have an answer here as an example:
h1 = figure(1)
plot(1:10,'o-r');
title('title');
xlabel('xlabel');
ylabel('ylabel');
% Copy contents
ch(1) = copyobj(gca,gcf);
% Figure 2
h2 = figure(2)
plot(1:30,'o-r');
title('title fig2');
xlabel('xlabel');
ylabel('ylabel');
% copy contents
ch(2) = copyobj(gca,gcf);
figure(3)
sh = subplot(1,2,1);
clear axes
p = get(sh,'position');
ah = copyobj(ch(1),gcf);
set(ah,'position',p);
% Create axis template
sh = subplot(1,2,2);
clear axes
p = get(sh,'position');
ah = copyobj(ch(2),gcf);
set(ah,'position',p);
% Delete template
% delete(sh);

Amro's solution works greatly, but with boxplots you have to reset the Xtick and Xtick labels, otherwise, for some reason, they will not be resized according to the the subplot. When you create the boxplot or after opening the figure add:
set(gca,'XTick',<1d vector>,'XTickLabel',<1d cell vector>)
or put automatic ticks and labels
set(gca,'XTickMode','auto','XTickLabelMode','auto')

Related

how to subplot n figures (pcolor) using for loop (matlab)

I have n saved fig files (all the figures are pcolor figure) and I want to plot all the figures in one new subplot (n X 2). Can anyone please help me out here? I will be really really grateful :)
% Open each figure and copy content
for i = 1:nFig
% Open fig-i
filename = fullfile(rep,list(i).name);
fighand = openfig(filename,'invisible');
h=subplot(nFig,2,i);
% Close fig-i
close(fighand)
end
You can use copyobj to copy the contents of an existing axes to a target axes. See comments for explanation:
N = 4;
%% generate some figs
fig = cell(1,N);
for k = 1:N
fig{k} = figure(k);
fig{k}.Name = sprintf('fig_%i', k);
pcolor(rand(10));
xlabel(sprintf('some xlabel %i',k))
ylabel(sprintf('some ylabel %i',k))
savefig(fig{k}, fig{k}.Name)
end
%% load figs and make nice subplot
fig_all = figure(99);clf;
for k = 1:N
% load figure
fig_tmp = openfig(sprintf('fig_%i', k),'invisible');
% set fig_all as the current figure again
figure(fig_all);
% create target axes
ax_target = subplot(N/2,2,k);
pcolor(ax_target, rand(5)*0.001); cla; % plot some random pcolor stuff to setup axes correctly
% get the source data and copy to target axes
ax_src = fig_tmp.Children;
copyobj(ax_src.Children, ax_target);
% set axes properties of target to those of the source
ax_target.XLim = ax_src.XLim;
ax_target.YLim = ax_src.YLim;
% copy the axes labels
ax_target.XLabel.String = ax_src.XLabel.String;
ax_target.YLabel.String = ax_src.YLabel.String;
end

Several graphs in 1 loop, each iteration adds a line on every figure

Trying to engineer the following in Matlab:
** loop start;
y(:,i) = function of x;
z(:,i) = function of x;
plot(x,y(:,i)) on figure 1, hold all;
plot(x,z(:,i)) on figure 2, hold all;
** loop end;
add title, legend, etc for figure 1 (NB: we have multiple lines);
add title, legend, ets for figure 2 (NB: same, have multiple lines for the legend);`
Tried multiple combinations without much luck. Managed to get 2 figures but only the 2-nd displays multiple lines, not the first. And can't figure how to add legends to these 2 correctly.
Save a handle to each figure, and to each axis object:
fh1 = figure;
hold all;
ah1 = gca;
fh2 = figure;
hold all;
ah2 = gca;
for i=1:N
y(:,i) = function of x;
z(:,i) = function of x;
plot(ah1, x, y(:,i)); %# tell it which axis to use (ah1)
plot(ah2, x, z(:,i)); %# (ah2)
end
legend(ah1, ...) %# legend options here
legend(ah2, ...) %# and the other legend
%# note: you can set figure properties for each using fh1, fh2 handles.
You can do this:
figHandle1 = figure(1);
figHandle2 = figure(2);
Then when you want to plot on that figure do this:
figure(figHandle1) %Plot on figure 1
%ie plot(someStuff)
figure(figHandle2) %Plot on figure 2
Also its the same for the title and stuff, you jjust need to identify which figure by doing:
figure(handle);
Hope this helps.

how to draw three graphics on the same figure?

That's how I draw two graphics (thanks for guys who helped me to do that):
clear
logsFolder = 'C:\logs\';
stocks = {'log'};
for stock = stocks
filename = [logsFolder stock{1} '.log'];
fLog = fopen(filename);
data = textscan(fLog, '%f:%f:%f:%f %f %f %f');
fclose(fLog);
% hh:min:sec:millisec
secvec = [60*60 60 1 1e-3];
x = [data{1:4}] * secvec';
y = data{5};
yPrice = data{6};
xindays = x / (24*60*60);
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
set(AX(1),'xtick',[]);
lo1 = min(y);
hi1 = max(y);
lo2 = min(yPrice);
hi2 = max(yPrice);
if (hi2/lo2 > hi1/lo1)
ylim(AX(1),[lo1 hi2/lo2 * lo1]);
ylim(AX(2),[lo2 hi2]);
else
ylim(AX(1),[lo1 hi1]);
ylim(AX(2),[lo2 hi1/lo1 * lo2]);
end
ticklabelformat(AX(2),'y','%g')
ticklabelformat(AX(2),'x',{#tick2datestr,'x','HH:MM:SS'})
title(stock);
% iNeedToDrawThat = data{7}
end
Input file example is available here As you can see my file contains the last column which I also want to display. The range should be from 0 (at the bottom of figure) to the maximum value (at the up of the graph). So I need to draw three graphics somehow. It's ok to omit axis with labels for the third graph as I already have two axis and I have no place to add third one. However it's ok to "overlap" two axis if possible.
I have no idea how to do that so I'm looking for your help.
I've tried that but it doesn't work:
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
I have already mentioned a similar question in the comments, it should give you plenty of ideas...
Anyway, I've put together a solution to plot multiple y axes. Right now the code is a bit involved, but it should be possible to refactor a re-usable function out of it (like the addaxis function on the File Exchange).
The idea is to first plot each curve in a separate axis (all superimposed), and make them transparent (except the bottom one). Next we create copies of this set of axes and shift them along the x-direction. We also make those copies transparent, but now we can show the tick-marks along the y-axis of each. Finally we give them correct z-order, and link the x and y limits so that we can use the pan and zoom functionality.
%# read and parse data from file
fid = fopen('log.log','rt');
C = textscan(fid, '%s %f %f %f', 'CollectOutput',true);
fclose(fid);
dt = datenum(C{1}, 'HH:MM:SS:FFF');
data = C{2};
NUM = size(data,2);
%# create a wider figure
hFig = figure('Position',get(0,'DefaultFigurePosition').*[1 1 1.7 1]);
%# some properties
clr = lines(NUM);
bgClr = get(0,'DefaultFigureColor');
pos = get(0,'DefaultAxesPosition');
pp = 0.1; % shift in normalized units: pos(1)
%# create plot axes (make axis invisible)
hAx = zeros(NUM,1);
for i=1:NUM
hAx(i) = axes('Parent',hFig, 'Color','none', ...
'XColor',bgClr, 'YColor',bgClr, ...
'Units','normalized', 'Position',pos+[(NUM-1)*pp 0 -(NUM-1)*pp 0]);
line(dt, data(:,i), 'Color',clr(i,:), 'Parent',hAx(i))
end
axis(hAx, 'tight') %# tight x/y limits
%# create shifted copies of axes to show y-ticks
hAxx = zeros(size(hAx));
for i=1:NUM
hAxx(i) = copyobj(hAx(i), hFig);
delete(get(hAxx(i),'Children')); %# keep only axis
set(hAxx(i), 'YColor',clr(i,:), ...
'Units','normalized', 'Position',pos+[(NUM-i)*pp 0 -(NUM-i)*pp 0]);
ylabel(hAxx(i), sprintf('Axis %d',i))
end
xlabel(hAxx(1), 'datetime')
title(hAxx(1), 'Log')
datetick(hAxx(1), 'x', 'HH:MM', 'keeplimits')
%# set 1st axis copy as current axis
set(hFig, 'CurrentAxes',hAxx(1))
%# adjust ticks of axes
set(hAx(1), 'Color','w') %# give white bg to 1st axis
set(hAxx(1), 'XColor','k') %# show xticks of 1st axis copy
set(hAxx(2:end), 'XTick',[], 'XTickLabel',[])
set(hAx, 'XTick',[], 'XTickLabel',[], 'YTick',[], 'YTickLabel',[])
%# fix z-order
for i=3:-1:1, uistack(hAxx(i),'top'), end
uistack(hAx(1), 'bottom')
%# link x/y limits so that panning/zooming works
lh = cell(NUM+1,1);
for i=1:NUM
lh{i} = linkprop([hAxx(i);hAx(i)], 'YLim');
end
lh{end} = linkprop([hAxx;hAx], 'XLim');
The result:
The panning/zooming is a bit funny, you have to initiate them by starting to drag from the side (the shifted colored axes). This is because the first one (corresponding to the blue line) is the one on top, thus catches all mouse clicks.
Note: I see you are using a custom function ticklabelformat, which I haven't tested in combination with the above code. I will leave that part to you..
HTH
sample use of hold on
figure;
plot(x1,y1);
hold on
plot(x2,y2);
plot(x3,y3);
hold off
do "figure" and "hold on" only once outside the loop. then plot all the graphs you need
figure;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
hold on;
volume = data{7};
plot(xindays, volume);
hold off;
if you do it the way you suggested using hold on, i.e. use plotyy() first then the axes won't adjust so if you 3rd series is out of the range of your first set of axes then it won't appear. Try just flipping them and see if that produces a result?
volume = data{7};
plot(xindays, volume);
hold on;
[AX,H1,H2] = plotyy(xindays,y,xindays,yPrice);
This way the axes should adjust
For example:
t = 1:10;
x = t*2;
y = t*-2;
z = x + 1000;
Now compare
plot(t,z, 'r')
hold on
plotyy(t,x, t,y)
to
plotyy(t,x, t,y)
hold on
plot(t,z, 'r')

Matlab, print() function generates a png file without Y asymptote data

I have been currently using a Matlab script that plots a function and prints its data into a png file, but I have a problem with this last phase.
The fact is that, moving from plotted image to png files, some data points disappear.
Here are my images.
What Matlab (correctly) plots (note that the maximum is (0; 7.7)):
And here's what Matlab prints into the file:
Note that all the points in the Y asymptote are missing!
Why does this happen?
Here's my code:
grafico2D('filename.dat', -1);
...
function [result] = grafico2D(filename, max_X)
% function that loads data from a two-column file and plot them in 2D image
close all;
dati = load(filename); % load data from file
X = dati(:,1); % X axis
Y = dati(:,2); % Y axis
temp = size(X);
lungX = temp(1);
hFig = figure();
set(hFig, 'Visible', 'on');
plot(X, Y, 'red');
hold on;
ylim([0 1]);
if(max_X==-1)
xlim([1 X(lungX)]);
else
xlim([1 max_X]);
end
xlim
title(strrep(filename,'_','\_')); % substitute _ with \_
xlabel('annotation prediction position'), ylabel('likelihood');
grid
print(hFig, '-dpng', filename); % stampa su file
% }
result = 1;
end
Is there someone who can help me?
Thanks!
You can increase the resolution of your image with the -r option which specifies the resolution in dot per inch (with 90 as default). It should solve your problem (at least it did for me). See the Matlab print function documentation.
PS: you could also use thicker lines with the line property LineWidth.
You could just extend the x-limit a little bit:
xlim(xlim() - [0.05 0])

How can I put a background image in a movie in matlab

I need to put a background image in a movie created using MATLAB?
I have posted below an example code of how I am generating a movie in Matlab. I need to add a background image to this movie. Thanks for your help.
for i=1:128
for j=1:128
p(i,j,:)=randn(1,200);
end
end
[u,v,w]=size(p);
frm_r=1:128;
frm_c=1:128;
figure; j=1;
for t=1:w
surface(frm_c,frm_r,p(:,:,t),'EdgeColor','none');
pause(0.1)
colorbar;
F(j) = getframe;
j=j+1;
end
movie(F,1,50)
If you have access to MATLAB code that creates movie, you can place an axes with IMAGE or IMSHOW as a background and make axes on the top of it transparent.
Here is a simple example:
im = image; % create image object (default pic)
imax = get(im,'parent'); % get image axes handle
axis ij
set(imax,'position',[0 0 1 1]) % make it to fill the whole figure
ax = axes; % new axes
h = plot(ax,rand(100),'ro'); % initial plot
for i=1:20
set(h,'ydata',rand(100,1)); % change the data in a loop
pause(0.1)
end
You can get get better answer if you show your code how you create a movie.
EDIT:
I simplified the code in your answer a little. For example you don't need loops to fill up 3D array. And you don't need to repeat surface function in the loop. Just change zdata property.
Try this code (substitute yourimage.jpg to real file name):
p = randn(128,128,200);
[u,v,w]=size(p);
frm_r=1:128;
frm_c=1:128;
figure;
im = imshow('yourimage.jpg'); % create and display image object from a file
imax = get(im,'parent'); % get image axes handle
set(imax,'position',[0 0 1 1]) % make it to fill the whole figure
ax = axes('color','none'); % new axes
hsurf = surface(frm_c,frm_r,p(:,:,1),'EdgeColor','none','Parent',ax);
colorbar;
xlim([1 u])
ylim([1 v])
j=1;
for t=1:w
set(hsurf,'zdata',p(:,:,t))
F(j) = getframe;
j=j+1;
end
movie(F,1,50)