FIG files format

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:

MAT-file preferences (note the FIG clarification)

MAT-file preferences (note the FIG clarification)

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!

Categories: Figure window, Handle graphics, Hidden property, Low risk of breaking in future versions, Stock Matlab function, Undocumented feature

Tags: , , ,

Bookmark and SharePrint Print

11 Responses to FIG files format

  1. Jos von Asmuth says:

    Hi Yair,

    Thanks again. Perhaps it is a simple issue, but do you happen to know how to, once loaded, create a gui or figure out of such a structure? It could be helpfull for automaticcally generating GUI’s.

    Kind regards,
    Jos

    • @Jos – You can use the struct2handle function for this. I will explain its usage next week. Of course, you can always use hgload on the original FIG filename.

  2. Volkmar Glauche says:

    I am using this feature to “repair” GUI figures created with some versions of guide. Some versions of guide store callbacks as function handles in a way that is not compatible with all versions of MATLAB I have to work with (R14SP3 onwards). I parse the function handles and replace them with a callback string (if possible).
    Also, in conjunction with gencode this is useful to read and modify the MATLAB code of a saved figure.

    Best,

    Volkmar

  3. Robin Lundberg says:

    Trying this in matlab 2014b still opens the gui (sometimes).
    When you load a gui you get

    >>figData = load('guiPostProcessing.fig', '-mat')
    figData = 
        hgS_070000: [1x1 struct]
        hgM_070000: [1x1 struct]

    And this might open the figure. To prevent this I did this instead and it seems to work fine

    >> figData = load('guiPostProcessing.fig', '-mat', 'hgS_070000')
    figData = 
        hgS_070000: [1x1 struct]
  4. Mariam says:

    Hi,

    I have used above following command to load the attributes of figures

    d = load('testFig.fig','-mat')

    and then changed those attributes. I want to know how could I apply new attributes to my figure or how can I save variable ‘d’ into .fig format. Please reply.

    Regards,
    Mariam

    • @Mariam – you can simply use the save command to save your modified d struct back into the *.fig file, and then open this FIG file normally:

      save('testFig.fig','d','-mat'); % save modified d struct
      testFig; % open figure
    • Mariam says:

      I already tried this and this the error I am getting

      >> save('C:\Users\Mariam\Desktop\fitted response\atlas masks\IPS_1.fig','s','-mat')
      >> open('C:\Users\Mariam\Desktop\fitted response\atlas masks\IPS_1.fig')
      ??? Error using ==> open at 163
      Invalid Figure file format
    • @Mariam – You probably updated your s data-struct incorrectly

    • Mariam says:

      I tried it without making any changes to ‘s’. Just loading it

      s = load('C:\Users\Mariam\Desktop\fitted response\atlas masks\IPS.fig','-mat');

      and re-saving it

      save('testFig.fig','s','-mat'); % save modified d struct

      However the effect remains it

      open('testFig.fig')
      ??? Error using ==> open at 163
      Invalid Figure file format.
    • @Mariam – the save command save the data including the variable name as top-level struct field. You should keep the same top-level field-name as used by the FIG format (hgS_070000 or hgM_070000):

      s = load('IPS.fig','-mat');
      hgS_070000 = s.hgS_070000;
       
      % modify hgS_070000
       
      save('IPS.fig','hgS_070000','-mat');
    • Martin says:

      @Mariam – you can also use the -struct flag of the save function, if you want to modify the struct s directly without going through another temporary variable:

      save('testFig.fig', '-struct', 's', '-mat');

      That way the field names of the struct s are treated as the variable names to be saved to the file.

Leave a Reply


Your email address will not be published. Required fields are marked *