Figure identity Question with Loops

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

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?
@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.

Sign in to comment.

Answers (2)

Geoff Hayes
Geoff Hayes on 13 Jul 2017
Edited: Geoff Hayes on 13 Jul 2017
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.
In later versions of MATLAB, the input to figure can be a number (see input n) where
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).

1 Comment

Thanks Geoff, Im using 2017a so will give it a go. J

Sign in to comment.

Jan
Jan on 17 Jul 2017
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

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!
"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.
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.
Jason
Jason on 18 Jul 2017
Edited: Jason on 18 Jul 2017
Hi Adam/Jan.
so in each iteration of my loop I plot about 8 subplots, so I need to know which current figure I am plotting to. This then begs the question - why not use gcf? Well, each loop takes about 10 mins, so often I switch back to my main GUI, or view an earlier figure, so these may then become the current figure.
If I was to plot to figure(n), how would you suggest that n is the last one that opened?
thanks Jason
"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.
"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.
But I would have to get n=last figure number opened + 1 at the start of each loop as I create the figure.
This is what I was trying to ask.
Maybe start with a very large number on the 1st loop i.e. figure(100)
Then use setappdata to store 100. i.e.
setappdata(0,'latestn',100)
Then on every other loop, do:
nn=getappdata(0,'latestn')
figure(nn)
Whats the view on this approach?
thanks Jason
Adam
Adam on 18 Jul 2017
Edited: Adam 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.
Jan
Jan on 18 Jul 2017
Edited: Jan on 18 Jul 2017
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.
Thanks Jan & Adam, I will take a look. Just out of interest, Walter suggested this sometime ago to close figures:
fig1h = findall(0,'type','figure','Tag','figure1'); %Keep this open as its the main gUI figure
figh = findall(0,'type','figure');
other_figures = setdiff(figh, fig1h);
delete(other_figures)
close all
will close all figures that aren't GUIDE figures too.

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Tags

Asked:

on 13 Jul 2017

Commented:

on 18 Jul 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!