Making use of figure numbers is discouraged – what are your workarounds?

11 views (last 30 days)
Quite a common task, I assume: based on a simulation or measurement run I generate a set of figures to display the results.
I find it convenient to group the figure numbers of a single run in a certain number range, say 1XXX or 2XXX. In this way I can compare specific results of different runs by quickly picking the windows of two figures, say 1003 and 2003.
But Matlab obviously discourages the use of figure numbers. As far as I know
  • figure(n, Name="Foo") or figure(Number=n, Name="Foo") is not supported, you need two lines
  • loading a .fig-file into a figure with a certain number is not supported
  • reassigning a figure number is not supported, the number is read-only
  • duplicating figures is not natively supported (why?), the copyobj workaround comes with too many limitations
Are there any workarounds to go on with figure numbers that I'm not aware of?
When you create a new figure, Matlab knows what figure number n to choose: the smallest positive integer that is not occupied by an existing figure. Can you somehow manipulate that n, except for creating dummy figures ;-)?
Or what is your trick of dealing with this common task? Prepend a number string to the figure name? The figure window name will read something like "Figure 23: 1003 Foo" – ugly.
Or am I missing something? Is there any usability rationale behind discouraging figure numbers, or is it just a long-standing limitation?
  1 Comment
Andres
Andres on 27 May 2024
Edited: Andres on 27 May 2024
It has now become clear that I am not interested in using the integer figure handle as a handle, but as an identifier with which I can organize figures and find a figure window (or file) in a larger number quickly and unambiguously. In principle, I would like to have a kind of number property that exists independently of the handle.
The tag property would be just as suitable if it could appear in the window name instead of the number (à la f.TagTitle = “on”).
So far, I have used the figure name only to describe the content of the figure. With a little bit of adaptation, I can also prefix it with an identifier. I therefore accept Ayush Modi's answer, but thank everyone for their contributions and would be happy to receive further suggestions.
I still wish there was a native way to duplicate/clone a figure, but that's another topic.

Sign in to comment.

Accepted Answer

Ayush Modi
Ayush Modi on 24 May 2024
Edited: Ayush Modi on 24 May 2024
Hi Andres,
As a workaround, you can disable the figure number. Then, the custom name provided will only be visible. Here is the sample code, that worked for me:
figure('Name','1001','NumberTitle','off');
Refer to the following documentation for more information:

More Answers (2)

Steven Lord
Steven Lord on 24 May 2024
Rather than trying to set the number, why not create an array of figure handles and use the number as an index into that array?
listOfFigures = gobjects(1, 1000);
listOfFigures(42) = figure; % Fill in one of those objects with a figure
listOfFigures(41) % Still a placeholder, hasn't been filled in with a figure yet
ans =
GraphicsPlaceholder with no properties.
listOfFigures(42) % Actual figure object
ans =
Figure (1) with properties: Number: 1 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
You can also check if an entry in the list is a figure. A GraphicsPlaceholder isn't a matlab.ui.Figure but the output of the figure function is.
hasFigure = @(n) isa(listOfFigures(n), "matlab.ui.Figure");
hasFigure(41) % no, still a placeholder
ans = logical
0
hasFigure(42) % yes
ans = logical
1
Or if you want to avoid having to create a vector of thousands or tens of thousands of GraphicsPlaceholder objects, you could use a dictionary.
d = configureDictionary('double', 'matlab.ui.Figure')
d = dictionary (double --> matlab.graphics.Graphics) with no entries.
d(42) = figure
d = dictionary (double --> matlab.graphics.Graphics) with 1 entry: 42 --> 1x1 Figure
isKey(d, 41) % no figure 41
ans = logical
0
isKey(d, 42)
ans = logical
1
f42 = d(42)
f42 =
Figure (2) with properties: Number: 2 Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
  2 Comments
Andres
Andres on 24 May 2024
Nice suggestions, thank you for your quick yet detailed answer. I'm now aware that my question more relates to convenient figure window management, see my comment on Harald's answer.
Steven Lord
Steven Lord on 24 May 2024
For a bit of history:
Why were figure handles numbers?
Long Long Ago (well before I started at MathWorks in 2001) we introduced Handle Graphics. At that point the classdef-based object system probably wasn't even a twinkle in someone's eye; Handle Graphics may even predate the original object system in MATLAB (see: Long Long Ago.) So we needed some way to allow users to access those Handle Graphics objects. MATLAB did that by returning numeric values that were associated with the graphics objects on screen. Functions like set and get knew that if it received the value double(1) as the first input that it should look for a graphics object associated with that number internally rather than treating it as the number 1.
The root object (0, now groot) and figures (positive integer values, now objects) had "nice" values by default [1] and people got in the habit sometimes of performing arithmetic (particularly on figure handles.) If the figure f I have open is equal to 1, why not make the next one f+1 or 2?
Pitfalls of numeric handles
On occasion, people got in trouble typing the numeric value of axes or line handles (which were not integer values) as they were displayed in the Command Window and expecting that to let them query or manipulate the axes or line. This has all the pitfalls that users repeatedly stumble into on MATLAB Answers with floating point numbers. You can still (for backwards compatibility) get the numeric handles of those graphics objects, but you probably shouldn't unless you're dealing with very old legacy code. And even most of those legacy codes likely will "just work" because the functions they call (set, get, etc.) have implementations in MATLAB that can handle both the old numeric representation and new object handle representation.
What should you use today?
Nowadays (since release R2014b), though, rather than fiddling with numeric values I recommend storing and manipulating the graphics objects (that are bona fide objects, not numbers kept on some list in the memory of MATLAB [2].)
Footnotes
[1] You can tell MATLAB (if you specifically want to avoid people using arithmetic or typing a literal number to access your graphics objects) to use non-integer valued numbers for figure handles. [You can't change that the root object was 0. But again, you shouldn't be using that, instead "I am groot" ;) ]
f = figure(IntegerHandle = false) % Note the Number property is []
f =
Figure with properties: Number: [] Name: '' Color: [1 1 1] Position: [671 558 577 433] Units: 'pixels' Use GET to show all properties
ax = axes(Parent = f);
double(f) % not an integer, and is more precise than is displayed in "format short"
ans = 162.0024
double(ax)
ans = 163.0012
[2] Of course everything is a number or a series of numbers in memory. Everything in a computer eventually boils down to 0 and 1, false and true, off and on, etc. But there's actual properties as data in the graphics objects; the handle isn't just an entry in a list mapping number to something on screen.

Sign in to comment.


Harald
Harald on 24 May 2024
Hi Andres,
I typically return the handle to the figure if I want to reuse it. If you have a lot of figures, you could create a struct to store those handles, e.g.
figs.num1003 = figure(...);
figs.num2003 = figure(...);
If you wish to store extra information with a figure, you could use the UserData property.
Particularly if these suggestions do not help, it would be great if you could share a code example that demonstrates the challenge you run into.
Best wishes,
Harald
  3 Comments
Harald
Harald on 27 May 2024
So, we are talking about figures saved to files? Then, I would consider providing all relevant information in the file names. Then, you do not even need to look at the preview to see what the figure displays.
Andres
Andres on 27 May 2024
I'm talking about a bunch of open figures and the OS's open window preview
Having an identifier displayed first in the window preview allows me to quickly navigate to the desired figure, without reading the full window name that may be less regularly structured than in the example above.
I got used to utilize the figure number for that purpose, but as mentioned, I could also add an identifying "prefix" tag to the figure name and set the NumberTitle property to "off".
Beyond that, yes, I usually include the figure name in the file name when I save the figure to a file, next to other information I need to see what the figure displays.

Sign in to comment.

Categories

Find more on Graphics Object Programming in Help Center and File Exchange

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!