Figure identity Question with Loops
Show older comments
Hi, I am creating a figure on each pass in a loop.
On this figure I do several plots (20 of them) but always plot to figure(1) and so don't want to go and replace my code. So obviously all the plots gets overwritten each time the loop is executed
Is it possible to add at the end of the loop a way to change the current figure so that on the next loop, the current one will be figure(1)?
Thanks Jason
2 Comments
Adam
on 17 Jul 2017
It isn't obvious what the problem is with replacing code rather than doing some coding gymnastics to try to force figure(1) to be something different each time. Why can't you just use figure(n) to plot to?
Stephen23
on 17 Jul 2017
@Jason: often in these kind of situations it turns out to be better to just go through the code and do it properly: fix it at the source rather than try to bandage it up later.
Answers (2)
Geoff Hayes
on 13 Jul 2017
Edited: Geoff Hayes
on 13 Jul 2017
0 votes
Jason - it may depend upon which version of MATLAB that you are using. In (at least) R2014a, the input parameter to figure is a handle so figure(1) will always refer to the figure whose handle is 1...and so you wouldn't be able to change the handle of a figure so that the newest figure is of handle 1.
figure(n) finds a figure in which the Number property is equal to n, and makes it the current figure. If no figure exists with that property value, MATLAB® creates a new figure and sets its Number property to n.
With that in mind, you might be able to change the Number property of the current figure and then set the Number property of the new figure to 1 so that figure(1) refers to that new figure. My version of MATLAB doesn't support this property, but perhaps someone else can comment on this.
An alternative, would be to pass the handle of your current figure into your function so that it gets updated rather than figure(1).
Jan
on 17 Jul 2017
0 votes
As far as I understand, your code always plot to figure(1). This is a bad idea and changing the code is the best solution. Let Matlab open a new figure for each diagram simply by omitting the number in the figure command. This is clean and easy, while addressing the figure(1) explicitely is the wrong approach, if you definitely do not want the figure(1) to be drawn in. Using some code to advance the figure number magically at the end of the loop, is too indirect to be clean.
11 Comments
Adam
on 17 Jul 2017
I have tended to find that using an explicit figure number is very useful when I am re-running the same code over and over again and I don't want to have to keep closing figures every time so I just force it to plot to the same one. This is usually just in a script though rather than 'proper' code and I never use '1', I just arbitrarily pick some number large enough that I am highly unlikely to already have that figure open for a different purpose!
Jan
on 17 Jul 2017
"Highly unlikely" means, that the code fails, when I want to demonstrate its success to my boss.
Sometimes I have the same demands: Running some code to create a bunch of figures. But it depends on the current job, if I want to replace the former set of figures or add a new set to compare the output. Therefore I add a "close this set" button to all figures belonging to a set. This can be adjusted easily to arrange the figures side by side also. Then it costs one mouse click only to have either the new set or to keep the old set also. In addition there are no collisions when I run different tools. All figures are addressed by the handles only and to keep a list of these handles of a figure set allows e.g. to print the complete set in one PDF. "Most likely not colliding" integer numbers for addressing are less powerful.
Adam
on 17 Jul 2017
Well, in my examples the code itself wouldn't fail, it would just obliterate whatever I happened to already have in figure 457 if I happened to have plotted something else in it previously that I wanted to keep.
But certainly I don't do this in real code, it is just for scripts where I am testing out ideas before I move them into proper code where more often than not I have axes embedded into a GUI rather than launching a random extra figure.
My scripts I often run multiple times in quick succession after some small tweaks so I just tend to end up with loads of figures open. I don't really want to spend time adding extra functionality to those figures though if they'll maybe only be relevant code for a day. And I certainly don't like to add the Matlab newbie's favourite 'close all' to my script! I will often do it on command line, but then it is a choice I make rather than an 'Oops, I didn't want to close that figure over there!'.
Something more robust is definitely advisable for code that is expected to have longevity though. I created a GUIManager class to control figures I launch from a main GUI since Matlab doesn't allow the concept of figures being parented by other figures and thus closing down when their would-be parent closes.
Stephen23
on 18 Jul 2017
"which current figure"
This does not make sense: there is only one current figure.
In any case: avoid gcf and other "fun-for-playing-in-the-command-window" functions, obtain and specify all graphics handles explicitly and you will avoid the entire situation that you have explained to us.
Adam
on 18 Jul 2017
"If I was to plot to figure(n), how would you suggest that n is the last one that opened?"
If you refer to it as figure(n) (or better keep a handle to it after creating it and use that) then it doesn't matter when it was opened.
Jason
on 18 Jul 2017
It does have the flaws Jan discusses in his answer so it depends whether this is a proper production piece of code or just a script for you to run yourself.
If it is the latter then there is no major problem with just picking a large number for your first figure and incrementing. If the former you are better off with a more robust approach of storing the figure handles when you create a new figure e.g.
hFig(n) = figure;
and plotting directly to that. If you are in a for loop then the loop control will presumably handle the incrementing, otherwise you can just keep a counter. Or you could use a map to link something other than just an incrementing loop control to your figure handles if that is too brittle.
I prefer to create a vector of figure handles at first and then store it in all figures belonging to the set. Here closing one figure closes all others also - but of course this would be more elegant if the user can choose to close a single figure also:
function main
nFig = 5;
nSub = 8;
FigHList = gobjects(1, nFig);
doInitialize = true;
for k = 1:100
iFig = mod(k, 5) + 1;
if ~ishandle(FigHList(iFig))
FigH = figure;
FigHList(iFig) = FigH;
else
if doInitialize
set(FigHList, 'CloseRequestFcn', ...
{@CloseFigureSet, FigHList});
doInitialize = false;
end
FigH = FigHList(iFig);
end
iSub = mod(k, 8) + 1;
AxesH = subplot(2, 4, iSub, 'Parent', FigH);
plot(1:10, rand(1, 10), 'Parent', AxesH);
end
end
function CloseFigureSet(FigH, EventData, FigHList)
for iFig = 1:numel(FigHList)
if ishghandle(FigHList(iFig)) % Security check
delete(FigHList(iFig));
end
end
end
!JUST FOR DEMONSTRATION! Not Tested!
Instead of the CloseRequestFcn I use a function to close all, close one, print all to PDF or save all in a created folder, lock the figure set from beeing killed by close all, arrange figures horizontally/vertically, etc. I can even give the figure set a unique name and can remove it automatically the next time the script runs. This avoids the ambiguities of using integer numbers to address the figures.
Jason
on 18 Jul 2017
Adam
on 18 Jul 2017
close all
will close all figures that aren't GUIDE figures too.
Categories
Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!