Showing multiple .fig files in one plot - matlab

I am trying to write a relatively simple function which allows me to plot any numbers of figures (previously saved as .fig files) one close to the other.
I have looked for the solution in the website, but it does not work for me.
Moreover, I am almost there with my code, since the outputs are almost what I want: indeed I get the two figures in the right position, but in two separate windows and a third window which is correctly merging the two inputs, but they look weird, with a lower resolution! So I get three outputs in total.
Here is my code, I hope you can help me.
(Try with your own .fig files and check if you also have the three wrong outputs like me).
function SubPlotFig (varargin)
for i = 1:nargin
hf = hgload(varargin{i});
ax(i) = findobj(hf,'Type','axes');
end
hc = figure;
for i = 1:nargin
subplot(1,2,i,ax(i));
copyobj(ax(i),hc);
end
Attachment_1
Attachment_2

When you call hgload, it will open a figure from a .fig file and display it. You are doing this inside of your first loop, so you will see a figure for each of the inputs. The figure that you see is exactly what you saved for each figure.
for i = 1:nargin
hf = hgload(varargin{i}); % <---- Creates a figure
ax(i) = findobj(hf,'Type','axes');
end
In the second loop, you create a subplot for each of the axes within the figures that you just opened. These of course are going to be smaller because you are now putting multiple axes within a figure that is the default size. They aren't really "low resolution", just smaller on the screen. If you want to make them bigger, then you'll want to increase your figure size.
% Create all of the subplots
hc = figure;
for i = 1:nargin
hax = subplot(1,2,i,ax(i));
copyobj(ax(i),hc);
colorbar(hax);
end
% Make sure we are using the jet colormap
colormap(jet)
% Get the current figure position
pos = get(hc, 'Position');
% Double the width since you now have two plots
set(hc, 'Position', [pos(1:2) pos(3)*2, pos(4)])

The problem was the colormap. Now it is solved. Here is the correct code, can be useful for others :)
function SubPlotFig (varargin)
for i = 1:nargin
hf = openfig(varargin{i},'reuse');
cm = colormap;
c(i) = findobj(hf,'Type','Colorbar');
ax(i) = findobj(hf,'Type','Axes');
end
hc = figure;
for i = 1:nargin
subplot(1,2,i,ax(i));
copyobj(ax(i),hc);
colormap(ax(i),cm);
copyobj([c(i),ax(i)],hc);
end

Related

Two saved figures, want them to show in a single graph in MATLAB

Let's say I have two figures stored in separate files A.fig and B.fig which contain two separate plots. Is there a way to load A.fig and then do something like hold on and then load B.fig in the figure created for A.fig so that I have both plots in the same axes?
I think the question is not really a duplicate of this one. The OP does not ask for a way to extract the data but for a way to combine the two stored figures. Admittedly, he could extract the data and plot it again. But there is a more elegant solution...
The actual plots are children of axes which is a child of figure. Therefore you can achieve what you want by copying the children of the second axes into the first axes with copyobj. Before that, load the figures with openfig. This method has the advantage to copy different types of 'plots' (line, area, ...).
The code to copy from B.fig to A.fig is as follows and works starting from R2014b:
fig1 = openfig('A');
fig2 = openfig('B', 'invisible');
copyobj(fig2.Children.Children, fig1.Children);
If you have a Matlab version prior to R2014b, you need to use the set and get functions since you cannot use .-notation. More information can be found here. You can either use gca to get the current axes after loading the figure like this:
fig1 = openfig('A');
ax1 = gca;
fig2 = openfig('B', 'invisible');
ax2 = gca;
copyobj(get(ax2,'children'), ax1);
... or get them manually from the figure-handle like this:
fig1 = openfig('A');
fig2 = openfig('B', 'invisible');
copyobj(get(get(fig2,'children'),'children'), get(fig1,'children'));
The following script creates two figures and then applies the above code to combine them.
If you are have Matlab version R2013b or higher, replace hgsave with savefig as suggested in the documentation.
%% create two figure files
x = linspace(0,2*pi,100);
figure; hold on;
plot(x,sin(x),'b');
area(x,0.5*sin(x));
set(gca,'xlim',[0,2*pi]);
hgsave('A');
figure; hold on;
plot(x,cos(x),'r');
area(x,0.5*cos(x),'FaceColor','r');
hgsave('B');
%% clear and close all
clear;
close all;
%% copy process
fig1 = openfig('A');
fig2 = openfig('B', 'invisible');
copyobj(get(get(fig2,'children'),'children'), get(fig1,'children'));
close(fig2);
This gives the following result if manually combined in subplots:

Plot is not reset

i need your help. My program reads a M-File which is a recorded Video.
To display each image i use "imagesc", because the image is saved as a 200x200 Matrix with normalized values ranging from 0 to 1.
After reading each image i do some calculus. The Result should be displayed as an overlay to the image(one Point, and one Line). With the code below this works as expected for the first iteration of the loop.
At all further iterations the image is redrawn(which is correct) but the Point and Line is not cleared.
How can i achieve that the plots are cleared when a new image is displayed.
I tried several variations with the "hold" command. But got no success.
Additional question(not that important):
Is it possible to exchange the "plot" commands below with "set"(especially for the Point)?
My program consist of several more Axes Elements which i cut out to keep the example simple. This means my UI is very slow with "plot" commands so i tried to speed it up with "set".
It works quite well, but I'm not sure if a simple Point can be displayed with "set".
Thanks in advance.
function work()
h_figure = figure('Name','MainFig');
hImage.ax = axes('Units', 'Pixels','Position', [50 375 200 200]);
imagesc('Parent',hImage.ax,'CData',zeros(200));
hImage.axc = get(gca, 'Children');
hProfileLeft.ax = axes('Position', [50 200 200 100]);
hProfileLeft.pl = plot(hProfileLeft.ax, 1:200);
for(frame = obj.Startframe:obj.Endframe)
imgIntens= obj.video.A.intens(:,:,frame);
ProfileResult = doSomeCalc(someArgs);
set(hImage.axc, 'CData', imgIntens); % Show Image(200x200 double)
hold(hImage.ax, 'on'); % Using hold so that plot is overlayed
plot(ProfileResult.peaks.x, ProfileResult.peaks.y,'Parent',hImage.ax); % Simple Point
plot(ProfileResult.corridor.left, 1:200, 'Parent',hImage.ax); % Line
set(hProfileLeft.pl,'YData', ProfileResult.trace); % Draw data to different axes
hold(hImage.ax, 'off');
end
end
I encountered the same annoying behavior. For me the conclusion was to manually call cla.
And use line instead of plot, it has more options (especially nice that you can label the lines yourself) and won't delete the plot when called, also returns you the handles. Once you got the handles you can delete them separately.

How to specify the axis size when plotting figures in Matlab?

Suppose that I have 2 figures in MATLAB both of which plot data of size (512x512), however one figure is being plotted by an external program which is sets the axis parameters. The other is being plotted by me (using imagesc). Currently the figures, or rather, the axes are different sizes and my question is, how do I make them equal?.
The reason for my question, is that I would like to export them to pdf format for inclusion in a latex document, and I would like to have them be the same size without further processing.
Thanks in Advance, N
Edit: link to figures
figure 1: (big)
link to smaller figure (i.e. the one whose properties I would like to copy and apply to figure 1)
For this purpose use linkaxes():
% Load some data included with MATLAB
load clown
% Plot a histogram in the first subplot
figure
ax(1) = subplot(211);
hist(X(:),100)
% Create second subplot
ax(2) = subplot(212);
Now link the axes of the two subplots:
linkaxes(ax)
By plotting on the second subplot, the first one will adapt
imagesc(X)
First, you have the following:
Then:
Extending the example to images only:
load clown
figure
imagesc(X)
h(1) = gca;
I = imread('eight.tif');
figure
imagesc(I)
h(2) = gca;
Note that the configurations of the the first handle prevail:
linkaxes(h)
1.Get the handle of your figure and the axes, like this:
%perhaps the easiest way, if you have just this one figure:
myFigHandle=gcf;
myAxHandle=gca;
%if not possible, you have to search for the handles:
myFigHandle=findobj('PropertyName',PropertyValue,...)
%you have to know some property to identify it of course...
%same for the axes!
2.Set the properties, like this:
%set units to pixels (or whatever you prefer to make it easier to compare to the other plot)
set(myFigHandle, 'Units','pixels')
set(myAxHandle, 'Units','pixels')
%set the size:
set(myFigHandle,'Position',[x_0 y_0 width height]) %coordinates on screen!
%set the size of the axes:
set(myAxHandle,'Position',[x_0 y_0 width height]) %coordinates within the figure!
Ok, based on the answer of #Lucius Domitius Ahenoba here is what I came up with:
hgload('fig1.fig'); % figure whose axis properties I would like to copy
hgload('fig2.fig');
figHandles = get(0,'Children');
figHandles = sort(figHandles,1);
ax(1) = findobj(figHandles(1),'type','axes','-not','Tag','legend','-not','Tag','Colorbar');
ax(2) = findobj(figHandles(2),'type','axes','-not','Tag','legend','-not','Tag','Colorbar');
screen_pos1 = get(figHandles(1),'Position');
axis_pos1 = get(ax(1),'Position');
set(figHandles(2),'Position',screen_pos1);
set(ax(2),'Position',axis_pos1);
This is the 'before' result:
and this is the 'after' result:
Almost correct, except that the aspect ratios are still off. Does anybody know how to equalize everything related to the axes? (I realize that I'm not supposed to ask questions when posting answers, however adding the above as a comment was proving a little unwieldy!)

Plotting an existing MATLAB plot into another figure

I used the plot command to plot a figure and then changed lots of its properties using set command. I also store the handle of the plot (say h1).
What I need is to use the handle to plot the same figure again later in my code. I checked the plot command and did not find any version that accepts handle. I also thought of getting the Xdata and Ydata and use them to re-plot the same figure.
What is the simplest solution?
Edit 1: A working sample code based on copyobj that PeterM suggested.
hf(1) = figure(1);
plot(peaks);
hf(2) = figure(2);
plot(membrane);
hf(3) = figure(3);
ha(1) = subplot(1,2,1);
ha(2) = subplot(1,2,2);
for i = 1:2
hc = get(hf(i),'children');
hgc = get(hc, 'children');
copyobj(hgc,ha(i));
end
Edit 2: I also found this function that can copy figures (including legend) into a subplot.
I have run into this situation before. Depending on what you are trying to do the function copyobj may be appropriate. This function lets you take the contents of one axes and copy it to a new figure.
Improving #PeterM nice answer, one easier way would be:
fig2H=copy(gcf) % or change gcf to your figure handle
But it depends on what you want, if you want only the axes, or the whole figureā€¦ (btw, it doesn't seem to copy the legend handle).
You can use saveas to save the figure in a file, and the open to load the exact same figure from this file.
This would be the laziest way to accomplish what you want.
% Sample plot
f1 = figure(1);
plot(0:0.1:2*pi, sin(0:0.1:2*pi));
f2 = figure(2);
% The code you need
saveas(f1, 'temp.fig')
f2 = hgload('temp.fig')
delete('temp.fig')
I have used the function figs2subplots (given in Edit2 in the original question) - it does the work and is very easy to use.

How can I move several existing plots to one subplot in MATLAB?

I have a function, myFunkyFigure, that takes in data, does some funky things, and returns an axis object for the figure it produces.
I would like to be able to invoke this function twice, creating two different figures:
fig(1) = myFunkyFigure(dataSet1);
fig(2) = myFunkyFigure(dataSet2);
Then I would like to put them into a subplot together.
Note that, because of the funkiness of myFunkyFigure, the following does not work.
subplot(2,1,1);
myFunkyFigure(dataSet1);
subplot(2,1,2);
myFunkyFigure(dataSet2);
I believe that I need something along the lines of copyobj, but I haven't been able to get that to work (I tried following a solution in Stack Overflow question Producing subplots and then combine them into a figure later in MATLAB but to no avail).
Obviously, we don't know how "funky" your figures are, but it should be noted in such a case that the cleanest solution would be to modify the function myFunkyFigure such that it accepts additional optional arguments, specifically the handle of an axes in which to place the plot it creates. Then you would use it like so:
hSub1 = subplot(2,1,1); %# Create a subplot
myFunkyFigure(dataSet1,hSub1); %# Add a funky plot to the subplot axes
hSub2 = subplot(2,1,2); %# Create a second subplot
myFunkyFigure(dataSet2,hSub2); %# Add a funky plot to the second subplot axes
The default behavior of myFunkyFigure (i.e. no additional arguments specified) would be to create its own figure and place the plot there.
However, to answer the question you asked, here's a way to accomplish this given that you are outputting the axes handles (not the figure handles) in the vector fig (note: this is basically the same solution as the one given in the other question, but since you mention having trouble adapting it I thought I'd reformat it to better fit your specific situation):
hFigure = figure(); %# Create a new figure
hTemp = subplot(2,1,1,'Parent',hFigure); %# Create a temporary subplot
newPos = get(hTemp,'Position'); %# Get its position
delete(hTemp); %# Delete the subplot
set(fig(1),'Parent',hFigure,'Position',newPos); %# Move axes to the new figure
%# and modify its position
hTemp = subplot(2,1,2,'Parent',hFigure); %# Make a new temporary subplot
%# ...repeat the above for fig(2)
The above will actually move the axes from the old figure to the new figure. If you want the axes object to appear in both figures, you can instead use the function COPYOBJ like so:
hNew = copyobj(fig(1),hFigure); %# Copy fig(1) to hFigure, making a new handle
set(hNew,'Position',newPos); %# Modify its position
Also note that SUBPLOT is only used here to generate a position for the tiling of the axes. You could avoid the need to create and then delete subplots by specifying the positions yourself.
The code from gnovice didn't work for me.
It seemed that a figure couldn't be made the child of another figure. For example hNew = copyobj(fig(1),hFigure); gave the error
Error using copyobj
Object figure[1] can not be a child of parent
figure[1]
Instead, I had to make the axes children of the new figure. This is the function I came up with
function []= move_to_subplots(ax,a,b)
% %
% Inputs:
% inputname:
% Outputs:
% name: description type units
% saved data: (does this overwrite a statically named file?)
% plots:
%
% Standard call:
%
%
% Written by C. Hogg Date 2012_06_01
%
%
debugmode=0;
hFigure=figure();
if ~exist('a')
a=ceil(sqrt(length(ax)));
end
if ~exist('b')
b=1;
end
if a*b<length(ax)|~exist('a')|~exist('b')
disp('Auto subplot sizing')
b=ceil(length(ax)/a);
end
for i=1:length(ax)
hTemp = subplot(a,b,i,'Parent',hFigure); %# Make a new temporary subplot
newPos = get(hTemp,'Position'); %# Get its position
delete(hTemp);
hNew = copyobj(ax(i),hFigure);
set(hNew,'Position',newPos)
end
%% Debug. Break point here.
if debugmode==1; dbstop tic; tic; dbclear all;end
end
This seems to work for me.