Figure behavior varies when calling custom plot on single line or multiple lines - matlab

function plot2(x)
hold on
fig = gcf();
ax = gca();
plot(ax, x)
fig.Visible = true;
figure('Visible', 'off')
hold off
end
Why does
>> plot2([1 2]); plot2([2 1])
create two figures, but
>> plot2([1 2])
>> plot2([2 1])
one? We have
plot2() <=> use 1 existing figure, create 1 new figure
>> plot2(); plot2() <=> use figure X, create figure Y, use figure Y, create figure Z.
>> plot2() >>plot2() <=> use figure X, create figure Y. use figure Y? create figure Z?
disp(gcf) before hold off show that new figs are being created in both cases, as in Figure (25), Figure (26).

Note that calling plot2([1 2]); drawnow(); plot2([2 1]) on a single line uses one figure the same as two separate plot2 calls. So at a high level it's likely due to the graphics buffer not being flushed when calling both on a single line without drawnow.
However, debugging we can see this is caused by the slightly odd order of operations called by your plot2 function, which has ambiguous handling of figures by relying on gcf and using calls to hold out-of-order and without specifying the hold target axes.
In the below lines, where I've written a code line it as an extract from plot2 during a given command call:
>> plot2([1 2]); plot2([2 1])
% Calling through "plot2([1 2])"
hold on % creates a figure and axes if one doesn't exist, or hold current
fig = gcf(); % gets the figure referenced by "hold"
ax = gca; % gets the axes referenced by "hold"
plot(ax,x) % plots on these axes
fig.Visible = true; % make the current figure visible
figure('Visible','off') % Create NEW figure, hidden. At this point you have 2 figures
hold off % does NOTHING, sets hold to "off" for new (invisible)
% figure which is the default anyway
% Calling through "plot2([2 1])"
hold on % holds "on" the CURRENT figure. This will depend whether the graphics buffer
% has been flushed. If not then the current figure is the hidden one created
% in the previous call, if it has then the current figure is the most recent
% visible figure. This is *not* specifically noted in the docs.
fig = gcf(); % gets the same figure referenced by "hold"
ax = gca; % gets the same axes referenced by "hold"
plot(ax,x) % plots on these axes
fig.Visible = true; % make the same "current" figure as above visible. When running with a
% graphics flush in between, this figure will already be visible
% due to the above behaviour
figure('Visible','off') % Create ANOTHER NEW figure, hidden.
% At this point you will have 3 figures!
hold off % does NOTHING, sets hold to "off" for new (invisible)
% figure which is the default anyway
You can verify my last comment about ending up with 3 figures using allFig = findall(0,'type','figure'); which will show all current figure objects including those which are hidden.

Related

Is there any way to save a subplot to a variable in MATLAB?

In a piece of code in matlab, I generate a figure in which 5 different subplots appear. I was hoping it is possible to save these subplots to variables so I can later call upon one of these subplots and have the same subplot open in its own figure (So they can each be viewed more accurately if desirable). Unfortunately I have not been able to figure out how to do this myself.
I know a figure as a whole can be saved to a variable in the way described here: https://nl.mathworks.com/matlabcentral/answers/160049-how-to-assign-a-plot-to-a-variable
But this only saves the figure for as long as it stays opened after you have first created it. On top of that, it doesn't say how to do the same for subplots.
I generate my subplots in the following way:
for i = 1:length(figuredata)
subplot(2,3,i); % select subplot
plot(figuredata{1,i},figuredata{2,i},'r.') , grid on; % plot the figure
title(figuretitles{i}); % set title
ylabel('SIN'), xlabel('COS'),grid on; % label the axes
axis([0 16384 0 16384]); axis('square'); % set axis range for x and y
end
Where figuredata is a 2 x 5 cell array containing the data for each of the 5 plots and figuretitles contains the titles of the subplots
Does anyone happen to know how I could achieve what I want?
One thing you need to understand first is the concept of graphics object handles. In MATLAB, a handle is a reference to a particular graphics object. You use the handle to access and change properties of the object. A handle and the actual object itself should be thought of as separate (but related) entities. For example:
hFigure = figure(); % Create figure window and return handle
clear hFigure % Clear variable containing handle
This creates a figure window and stores the handle to the window in variable hFigure, then clears the variable. However, the figure still exists, because we only discarded a handle that referred to the object. Alternatively:
hFigure = figure(); % Create figure window and return handle
delete(hFigure); % Delete the graphics object
get(hFigure) % Use handle to try and access the object properties
Error using matlab.ui.Figure/get
Invalid or deleted object.
This creates a figure window, stores the handle to the window in a variable, then deletes the figure. When the object is deleted, the handle is no longer valid, and you get an error if you try to use it.
With this now in mind, there are a few options you have for moving, saving, and redisplaying graphics objects. Assuming you have an existing subplot (i.e. an axes object) that hasn't been closed or deleted, you can reparent the object to a new window by modifying the Parent property. For example:
hAxes = subplot(2, 2, 1);
plot(hAxes, [1 2], [1 2], 'r');
hFigure = figure();
set(hAxes, 'Parent', hFigure);
This will create a subplot, then move it to a new window. Note that the axes no longer exists in the original window, but it still has the same position, size, etc. that it had. If you want it to appear differently (i.e. a larger plot to fill the new window), you'll have to modify its properties after moving it.
Another alternative is to use the copyobj function:
hAxes = subplot(2, 2, 1);
plot(hAxes, [1 2], [1 2], 'r');
hFigure = figure();
copyobj(hAxes, hFigure);
This will make a copy of the axes object, so that there are now two independent graphics objects, one in each window.
If you're dealing with a situation where the original figure will be closed, and you want to save a copy of the axes objects so that you can redisplay them later, you can do this with the undocumented (or semi-documented) functions handles2struct and struct2handle. Here's an example that creates an axes with a line plotted in it, stores the axes object structure in a .mat file (using save), then loads the structure and adds it to a new figure:
hAxes = subplot(2, 2, 1);
plot(hAxes, [1 2], [1 2], 'r');
axesStruct = handle2struct(hAxes);
save('Axes_data.mat', 'axesStruct');
clear all;
close all;
load('Axes_data.mat');
hFigure = figure();
hAxes = struct2handle(axesStruct, hFigure);

How do I resize a figure window to cover the entire screen on MATLAB 2014 (b) +? [duplicate]

I am creating some figures in MATLAB and automatically save them to files. The problem that by definition the images are small. A good way to solve my problem by hand is to create an image (figure), maximize it, and save to a file.
I am missing this step of automatically maximize a figure.
Any suggestions?
Up till now I only found this:
http://answers.yahoo.com/question/index?qid=20071127135551AAR5JYh
http://www.mathworks.com/matlabcentral/newsreader/view_thread/238699
but none are solving my problem.
This worked for me:
figure('units','normalized','outerposition',[0 0 1 1])
or for current figure:
set(gcf,'units','normalized','outerposition',[0 0 1 1])
I have also used MAXIMIZE function on FileExchange that uses java. This is true maximization.
For an actual Maximize (exactly like clicking the maximize button in the UI of OS X and Windows)
You may try the following which calls a hidden Java handle
figure;
pause(0.00001);
frame_h = get(handle(gcf),'JavaFrame');
set(frame_h,'Maximized',1);
The pause(n) is essential as the above reaches out of the Matlab scape and is situated on a separate Java thread. Set n to any value and check the results. The faster the computer is at the time of execution the smaller n can be.
Full "documentation" can be found here
As of R2018a, figure as well as uifigure objects contain a property called WindowState. This is set to 'normal' by default, but setting it to 'maximized' gives the desired result.
In conclusion:
hFig.WindowState = 'maximized'; % Requires R2018a
Furthermore, as mentioned in Unknown123's comments:
Making figures maximized by default is possible using:
set(groot, 'defaultFigureWindowState', 'maximized');
Maximizing all open figures is possible using:
set(get(groot, 'Children'), 'WindowState', 'maximized');
More information about 'WindowState' as well as other properties controlling figure appearance can be found in this documentation page.
Finally, to address your original problem - if you want to export the contents of figures to images without having to worry about the results being too small - I would highly recommend the export_fig utility.
To maximize the figure, you can mimic the sequence of keys you would actually use:
ALT-SPACE (as indicated here) to access the window menu; and then
X to maximize (this may vary in your system).
To send the keys programmatically, you can use a Java-based procedure similar to this answer, as follows:
h = figure; %// create figure and get handle
plot(1:10); %// do stuff with your figure
figure(h) %// make it the current figure
robot = java.awt.Robot;
robot.keyPress(java.awt.event.KeyEvent.VK_ALT); %// send ALT
robot.keyPress(java.awt.event.KeyEvent.VK_SPACE); %// send SPACE
robot.keyRelease(java.awt.event.KeyEvent.VK_SPACE); %// release SPACE
robot.keyRelease(java.awt.event.KeyEvent.VK_ALT); %// release ALT
robot.keyPress(java.awt.event.KeyEvent.VK_X); %// send X
robot.keyRelease(java.awt.event.KeyEvent.VK_X); %// release X
VoilĂ ! Window maximized!
As it is proposed by an author above, if you want to simulate clicking the "maximize" windows button, you can use the code that follows. The difference with the mentionned answer is that using "drawnow" instead of "pause" seems more correct.
figure;
% do your job here
drawnow;
set(get(handle(gcf),'JavaFrame'),'Maximized',1);
imho maximizing the figure window is not the best way to save a figure as an image in higher resolution.
There are figure properties for printing and saving. Using these properties you can save files in any resolution you want. To save the files you have to use the print function, because you can set an dpi value. So, firstly set the following figure properties:
set(FigureHandle, ...
'PaperPositionMode', 'manual', ...
'PaperUnits', 'inches', ...
'PaperPosition', [0 0 Width Height])
and secondly save the file (for example) as png with 100dpi ('-r100')
print(FigureHandle, Filename, '-dpng', '-r100');
To get a file with 2048x1536px set Width = 2048/100 and Height 1536/100, /100 because you save with 100dpi. If you change the dpi value you also have to change the divisor to the same value.
As you can see there is no need for any extra function from file exchange or java-based procedure. In addition you can choose any desired resolution.
you can try this:
screen_size = get(0, 'ScreenSize');
f1 = figure(1);
set(f1, 'Position', [0 0 screen_size(3) screen_size(4) ] );
%% maximizeFigure
%
% Maximizes the current figure or creates a new figure. maximizeFigure() simply maximizes the
% current or a specific figure
% |h = maximizeFigure();| can be directly used instead of |h = figure();|
%
% *Examples*
%
% * |maximizeFigure(); % maximizes the current figure or creates a new figure|
% * |maximizeFigure('all'); % maximizes all opened figures|
% * |maximizeFigure(hf); % maximizes the figure with the handle hf|
% * |maximizeFigure('new', 'Name', 'My newly created figure', 'Color', [.3 .3 .3]);|
% * |hf = maximizeFigure(...); % returns the (i.e. new) figure handle as an output|
%
% *Acknowledgements*
%
% * Big thanks goes out to Yair Altman from http://www.undocumentedmatlab.com/
%
% *See Also*
%
% * |figure()|
% * |gcf()|
%
% *Authors*
%
% * Daniel Kellner, medPhoton GmbH, Salzburg, Austria, 2015-2017
%%
function varargout = maximizeFigure(varargin)
warning('off', 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame')
% Check input variables
if isempty(varargin)
hf = gcf; % use current figure
elseif strcmp(varargin{1}, 'new')
hf = figure(varargin{2:end});
elseif strcmp(varargin{1}, 'all')
hf = findobj('Type', 'figure');
elseif ~isa(varargin{1}, 'char') && ishandle(varargin{1}) &&...
strcmp(get(varargin{1}, 'Type'), 'figure')
hf = varargin{1};
else
error('maximizeFigure:InvalidHandle', 'Failed to find a valid figure handle!')
end
for cHandle = 1:length(hf)
% Skip invalid handles and plotbrowser handles
if ~ishandle(cHandle) || strcmp(get(hf, 'WindowStyle'), 'docked')
continue
end
% Carry the current resize property and set (temporarily) to 'on'
oldResizeStatus = get(hf(cHandle), 'Resize');
set(hf(cHandle), 'Resize', 'on');
% Usage of the undocumented 'JavaFrame' property as described at:
% http://undocumentedmatlab.com/blog/minimize-maximize-figure-window/
jFrame = get(handle(hf(cHandle)), 'JavaFrame');
% Due to an Event Dispatch thread, the pause is neccessary as described at:
% http://undocumentedmatlab.com/blog/matlab-and-the-event-dispatch-thread-edt/
pause(0.05)
% Don't maximize if the window is docked (e.g. for plottools)
if strcmp(get(cHandle, 'WindowStyle'), 'docked')
continue
end
% Don't maximize if the figure is already maximized
if jFrame.isMaximized
continue
end
% Unfortunately, if it is invisible, it can't be maximized with the java framework, because a
% null pointer exception is raised (java.lang.NullPointerException). Instead, we maximize it the
% straight way so that we do not end up in small sized plot exports.
if strcmp(get(hf, 'Visible'), 'off')
set(hf, 'Units', 'normalized', 'OuterPosition', [0 0 1 1])
continue
end
jFrame.setMaximized(true);
% If 'Resize' will be reactivated, MATLAB moves the figure slightly over the screen borders.
if strcmp(oldResizeStatus, 'off')
pause(0.05)
set(hf, 'Resize', oldResizeStatus)
end
end
if nargout
varargout{1} = hf;
end
This is the shortest form
figure('Position',get(0,'ScreenSize'))
I recommend the set command to change MenuBar and Toolbar properties of your figure. The set command is more versatile because it works for older and newer versions of Matlab.
fig = figure(1);
set(fig, 'MenuBar', 'none');
set(fig, 'ToolBar', 'none');
Now you can use set again to make your figure full screen.
set(fig, 'Position', get(0,'Screensize'));
Note that if you make the figure full screen first, and then remove the MenuBar and Toolbar, the figure will not be full screen, so make sure to run these in the correct order.

Matlab plot multiple figures without window

I am trying to plot with hidden Matlab figures to speed up my plotting:
a=1:10; b=-a;
% make invisible plot window
f = figure('visible','off');
g = figure('visible','off');
% figure makes the plot visible again
figure(f)
plot(a)
saveas(f,'newout','fig')
figure(g)
plot(b)
saveas(g,'newout2','fig')
%% load saved figures
openfig('newout.fig','new','visible')
openfig('newout2.fig','new','visible')
The problem is the figure(f) command that makes the plot window visible again.
The code plots without figure window when I only have one plot and figure(f) is not called.
I just learned that instead of calling figure(f) one should use set:
set(0, 'currentfigure', g);
This will change the current figure handle without changing its visibility.
The corrected version works as expected:
a=1:10; b=-a;
% make invisible plot window
f = figure('visible','off');
g = figure('visible','off');
% figure makes the plot visible again
set(0, 'currentfigure', f);
plot(a)
saveas(f,'newout','fig')
set(0, 'currentfigure', g);
plot(b)
saveas(g,'newout2','fig')
%% load saved figures
close all
openfig('newout.fig','new','visible')
openfig('newout2.fig','new','visible')
I would suggest making a whole new plot window. By doing that you will get two different plots, and as you say that only one plot works, i think it could work.
An alternative solution is to reference the axes within the plot command (instead of changing the current figure before plot):
a=1:10; b=-a;
f = figure('visible','off');
fax = gca; %// get handle to axes of figure f
g = figure('visible','off');
gax = gca; %// get handle to axes of figure g
plot(fax, a) %// plot in axes of figure f
saveas(f,'newout','fig')
plot(gax, b) %// plot in axes of figure g
saveas(g,'newout2','fig')
openfig('newout.fig','new','visible')
openfig('newout2.fig','new','visible')

How to suppress figures?

How can I suppress the display of a figure window while keeping the plotting in the background for saving the resulting plot at the end of run? What is the best practice to do this? At present, my code is like this:
showPlot = 1; % switch to turn plotting on/off
fig = figure(1); clf; hold on;
lineHandle = line(nan, nan);
total = 0;
for i = 1:10000
% long calculation
total = total + 1;
set(0, 'CurrentFigure', fig);
xlim([0, total]);
x = [get(lineHandle, 'XData'), total];
y = [get(lineHandle, 'YData'), rand()];
set(lineHandle, 'XData', x, 'YData', y);
drawnow;
end
% saveas(gcf, file, 'png');
I want to set up the code in such a way that when I set showPlot to 0, the figure window is not shown but the plot is saved to file.
To make the current figure not visible:
set(gcf,'visible','off')
From the MathWorks-reference:
To avoid showing figures in MATLAB you can start MATLAB using the noFigureWindows option. This option is not available on UNIX.
matlab -noFigureWindows
As an alternative you can change the default figure properties of the MATLAB root object:
set(0,'DefaultFigureVisible','off')
If you want to temporarily suppress new figures that should be accesable later in the same session you can save the figure handle:
set(0,'DefaultFigureVisible','off');
%create invisible figure 1
h(1)=figure;
%create invisible figure 2
h(2)=figure;
set(0,'DefaultFigureVisible','on');
%show figure 1
figure(1)
By the way, close all closes all currently open figures.
The other answers were not working for me on R2015b on Ubuntu, my figure window would always show up.
I am processing 100+ files and the figure window popping up prevents me from using my computer while processing the files.
Here's a workaround, launch matlab without a display:
matlab -nodesktop -nodisplay
and this will prevent figure windows from showing up. Programmatically saving the figure to a file still works.
As answered earlier, to suppress displaying figures during instantiation first call
set(0, 'DefaultFigureVisible', 'off');
% or, if post Matlab R2014b
set(groot, 'DefaultFigureVisible', 'off');
After this call, creation of new figures in a script will not result in a visible window popping up. Naturally, the way to revert this setting is
set(0, 'DefaultFigureVisible', 'on');
% or, if post Matlab R2014b
set(groot, 'DefaultFigureVisible', 'on');
The "gotcha" is that activating an existing figure for further manipulation will result in a visible window - if done incorrectly:
% suppress visible plot window creation
set(groot, 'DefaultFigureVisible', 'off');
figure(1); % will not result in a visible window
plot(0:.01:pi,sin(0:.01:pi));
hold on
figure(2); % still no visible window
plot(0:.01:10,(0:.01:10).^2);
% so far so good
% ... other statements ...
% select figure 1 to add to it:
figure(1); % visible window appears!
plot(0:.01:pi,cos(0:.01:pi));
hold off;
% ...
The workaround is to use another set command to select existing figures:
set(groot, 'DefaultFigureVisible', 'off');
figure(1); % will not result in a visible window
plot(0:.01:pi,sin(0:.01:pi));
hold on
figure(2); % still no visible window
plot(0:.01:10,(0:.01:10).^2);
set(groot, 'CurrentFigure', 1); % still no visible window
% plot commands will apply to figure 1
plot(0:.01:pi,cos(0:.01:pi));
hold off
% ...
Regardless of the setting of 'DefaultFigureVisible', calling
figure(h);
where h is a handle or integer for an existing plot window causes that window to become active and visible. Thus, one can make all plots visible at the bottom of a script this way:
fh = get(groot, 'Children');
for x = 1:numel(fh)
figure(fh(x));
end

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.