A short while ago, a StackOverflow user asked how to extract data from FIG files in Matlab. The answer to this question is easy, but I wish to use the opportunity to show how this can be useful in Matlab applications.
The need: load a FIG without displaying it
In data-processing applications, we often present data in graphs that can then be manipulated and saved for later use. In Matlab, saving is done interactively (via the figure’s File/Save menu option or via the figure’s Save toolbar button), or programmatically (via the hgsave function). In all cases, the data is stored in a *.FIG file (the FIG extension can actually be changed, but I really don’t see why).
The point is that in order to re-load the stored data, we need to use hgload, which has a nasty side-effect of actually displaying the stored figure.
This is bad in terms of performance and memory, especially for heavily-laden GUI figures, not to mention the fact that sometimes we do not want to display the GUI at all. We often just need to extract a sub-set of the stored information (for example, the plot values), without having to display the figure.
The answer: FIGs are simply MATs in disguise
Here’s where the undocumented stuff enters:
It seems that a FIG file is simply a hierarchical structure of all the non-default properties of the stored figure and its descendant handles, all this stored within a simple MAT file.
This is hinted in several places, for example in hgsave‘s doc page, and in the MAT-file preferences panel:
Knowing this, we can easily load the data, without displaying the figure, by using load(filename,’-mat’) rather than hgload. For example:
% Create and store a simple plot figure >> figure('Name','Test #1'); >> plot(1:9, sqrt(1:9)); >> hgsave(gcf,'testFig'); % Load the figure data >> d = load('testFig.fig','-mat') d = hgS_070000: [1x1 struct] % a Matlab 7 figure % Investigate the figure data >> d.hgS_070000 ans = type: 'figure' handle: 1 properties: [1x1 struct] children: [1x1 struct] special:  >> d.hgS_070000.children ans = type: 'axes' handle: 176.08251953125 properties: [1x1 struct] children: [1x1 struct] special: [4x1 double] >> d.hgS_070000.children.children ans = type: 'graph2d.lineseries' handle: 177.0830078125 properties: [1x1 struct] children:  special:  >> d.hgS_070000.children.children.properties ans = Color: [0 0 1] XData: [1 2 3 4 5 6 7 8 9] YData: [1 1.4142 1.7321 2 2.2361 2.4495 2.6458 2.8284 3] ApplicationData: [1x1 struct] XDataJitter: 0 XDataMode: 'manual' ObeyXDataMode: 'auto' ... % Extract plot data >> YData = d.hgS_070000.children.children.properties.YData YData = 1.0000 1.4142 1.7321 2.0000 2.2361 2.4495 2.6458 2.8284 3.0000
We see a couple of interesting things in this simple example:
First, note that the top-level structure node is called “hgS_070000” – we’ll dig into this next week. Basically, it indicates that the structure holds a Matlab 7 figure.
Secondly, we see hidden/undocumented properties of the stored objects (for example, the lineseries’ XDataJitter and ObeyXDataMode properties). ApplicationData is such a hidden handle, which is widely used as a substitute for any handle’s UserData property (the built-in setappdata and getappdata functions are simply wrappers for accessing this property using standard set and get functions).
Have you used the FIG/MAT feature for any useful functionality? If so, please do share your experience in a comment.
Next week, I will explain how looking under hgsave‘s hood leads to useful functions and to an interesting insight about Matlab’s future. Merry Christmas everybody!