I have a boxplot that is saved as a figure in Matlab. Unfortunately, I do not have the original data. How do I retrieve the data using code or the user interface?
You may be more precise on your question but here is an example with a simple plot. It shoule be the same with boxplot. It is all about getting axes children.
open myfig.fig; % open your fig file
h = gca; % get the handle of the current axes
hPlot = h.Children; % The children of the axes should be the plot line
XData = hPlot.XData;
YData = hPlot.YData;
Related
I'm working with the following Code to copy a saved plot into another.
fig1 = openfig('ABC.fig');
fig2 = openfig('DEF.fig', 'invisible');
copyobj(fig2.Children.Children, fig1.Children);
This works fine, as long as I'm not using a legend in fig2, then I get a Error message for using too many input arguments in copyobj. In the documentation I learnt, that copyobj doesn't copy the context menu of legends, so I'm asking for your help in copying the legend as well.
As shown here:
plot(rand(2))
l = legend('show'); % legend
ax = gca; % associated axes
fnew = figure;
copyobj([l,ax],fnew)
% This is what the error was telling you.
% You need to pass your axes object
% along with you legend object as an array of graphic objects
[l,ax]
ans =
1×2 graphics array:
Graphics Graphics
A colleague has passed me a .fig file that has many lines on the same plots and they are coloured based on which group they belong to. The figure is shown below for reference.
I need to change the legend so that lines with the same colour have the same legend entry. The problem is that I don't have access to the raw data so I can't use the method mentioned here so is there a way to change the legend entries just using the .fig file? I tried changing some of the legend names to NaN in the property inspector but that just changes the entries to NaN.
If you have the *.fig file you can extract any included data with the 'get' method if you have understood the MATLAB Graphics Objects Hierarchy.
For example, see the left plot below as example of your *.fig file. you can extract the data in there by digging through the Children of your current figure object.
% Open your figure
fig = openfig('your_figure.fig');
% fig = gcf % If you have the figure already opened
title('loaded figure')
% Get all objects from figure (i.e. legend and axis handle)
Objs = get(fig, 'Children');
% axis handle is second entry of figure children
HA = Objs(2);
% get line objects from axis (is fetched in reverse order)
HL = flipud(get(HA, 'Children'));
% retrieve data from line objects
for i = 1:length(HL)
xData(i,:) = get(HL(i), 'XData');
yData(i,:) = get(HL(i), 'YData');
cData{i} = get(HL(i), 'Color');
end
xy data of all lines in the figure is now extracted to xData and yData. The color information is saved to cell cData. You can now replot the figure with a legend the way you want (e.g. using the SO solution you found already):
% Draw new figure with data extracted from old figure
figure()
title('figure with reworked legend')
hold on
for i = 1:length(HL)
h(i) = plot(xData(i,:), yData(i,:), 'Color', cData{i});
end
% Use method of the SO answer you found already to combine equally colored
% line objects to the same color
legend([h(1), h(3)], 'y1', 'y2+3')
Result is the plot below on the right, where each color is only listed once.
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:
I have a saved figure (.Fig) containing some axes like this:
When I open this figure in MATLAB R2015a GUIDE I have this:
Is anyway to extract data from every axes in this figure? If not, is anyway to extract one of the axes in the figure and use it in another figure created by GUIDE?
Assuming the figure of interest is the current figure:
ax = get(gcf,'children'); % get all subplots
X=[];Y=[];
for iax = 1:length(ax)
child = get(ax(iax),'children'); % for each subplot, get all lines
for ichild = 1 : length(child)
X{end+1} = get(child(ichild),'xdata');
Y{end+1} = get(child(ichild),'ydata');
end
end
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.