Matlab figure 'age'
Asked Answered
K

3

7

Here's a question for 'experts in the less documented part of Matlab': is there a (undocumented?) way to determine how long a figure has been open for (i.e. the 'age' of the figure)?

figure; spy;
myfig=gcf;
age=get_age() %shoud output age of figure in some format
Klystron answered 3/2, 2018 at 13:23 Comment(0)
T
8

You can use the following mechanism:

First, create a small Matlab function as follows, that attaches the CreationTime property to a figure:

function setCreationTime(hFig,varargin)
   hProp = addprop(hFig,'CreationTime');
   hFig.CreationTime = now;
   hProp.SetAccess = 'private'; %make property read-only after setting its initial value

   hProp = addprop(hFig,'Age');
   hProp.GetMethod = @(h,e) etime(datevec(hFig.CreationTime), clock); %compute on-the-fly
   hProp.SetAccess = 'private'; %make property read-only
end

Now assign this function as the default CreateFcn callback function for all new figures from now on:

set(0,'DefaultFigureCreateFcn',@setCreationTime)

That's it - you're done!

For example:

>> newFig = figure;
>> newFig.CreationTime
ans =
      737096.613706748

>> ageInDays = now - newFig.CreationTime
ageInDays = 
       0.01625078368466347
>> ageDuration = duration(ageInDays*24,0,0)
ageDuration = 
  duration
   00:23:24
>> ageString = datestr(ageInDays, 'HH:MM:SS.FFF')
ageString = 
    '00:23:24.068'

>> ageInSecs = newFig.Age
ageInSecs =
    1404.067710354923808
Trammell answered 5/2, 2018 at 12:50 Comment(3)
picky picky... I added the extra steps to my answerTrammell
Please excuse pickiness - I did not know about the CreateFcn, that's genius. If you change setCreationTime to include addprop(hFig,'age'); hFig.age = @() etime((hFig.CreationTime),(clock)); then using feval(newFig.age) you get the time in seconds!Klystron
I updated the answer by adding an Age computed property. Using the property's GetMethod avoids the need to use feval. Also note that in your comment you forgot datevec()...Trammell
L
5

As far as I know, the figure object doesn't expose this kind of information. Not even in its undocumented underlying Java class. But I have an idea that may represent a nice workaround to this problem.

Use the following overload of the figure function:

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.

in order to assign an "unique identifier" to every existing figure, and associate these identifiers to a datenum value that represents the creation time:

% Initialize the lookup table somewhere in your code:
lookup_table = zeros(0,2);
% Together with a variable that stores the next unique identifier to be assigned:
next_id = 1;

% When you need to instantiate a new figure...
    % 1) Retrieve the current datetime:
    cdate = now();
    % 2) Update the lookup table:
    lookup_table = [lookup_table; next_id cdate];
    % 3) Initialize the new figure:
    figure(next_id);
    % 4) Increment the next unique identifier:
    next_id = next_id + 1;

Every row of the lookup table will then contain an unique figure identifier and its respective creation date.

Everything else is pretty easy to handle. When you want to query a figure uptime... find its unique identifier in the lookup table and subtract the current time (obtained using the now() command) to the creation time. I recommend you to to define a CloseRequestFcn handle for every figure you create, so that when a figure is closed, you can update the lookup_table and remove it. The identifier you assigned to a specific figure can be retrieved using its Number property. Here is a full working implementation:

global lookup_table;
global next_id;

lookup_table = zeros(0,2);
next_id = 1;

f1 = create_figure();
f2 = create_figure();

pause(10);

f1_ut = get_figure_uptime(f1)
f2_ut = get_figure_uptime(f2)

function f = create_figure()
    global lookup_table;
    global next_id;

    cdate = now();

    f = figure(next_id);
    f.CloseRequestFcn = @update_lookup_table; 

    lookup_table = [lookup_table; next_id cdate];
    next_id = next_id + 1;
end

function ut = get_figure_uptime(f)
    global lookup_table;

    tn = now();
    tc = lookup_table(lookup_table(:,1) == f.Number,2);

    if (isempty(tc))
        ut = -1;
    else
        ut = etime(datevec(tn),datevec(tc));
    end
end

function update_lookup_table(f,~)
    global lookup_table;
    lookup_table(lookup_table(:,1) == f.Number,:) = [];

    delete(f);
end

Alternatively, as you suggested in your comment, you can add a property to every figure you create in which its creation time can be stored. It's much more immediate and eliminates the need to handle a lookup table. For this, just use the addprop functon as follows:

cdate = now();

f = figure();
addprop(f,'CreationTime');
f.CreationTime = cdate;
Leyva answered 3/2, 2018 at 13:47 Comment(3)
I like the idea; I think I would rather store the actual time of creation in the figure object. As a side question: Can this be done easily? I noticed myfig.time=now(); throws an error and so does addproperty(myfig,'time');Klystron
Then you have to use addprop(myfig,'time');. It works.Leyva
Just for ref: I would probably also add an anonymous function for the figure called myfig.age=@(CreationTime) now()-CreationTime (<- pseudocode) so the age can easily be 'mined' out of the figure with myfig.age(myfig.CreationTime). If there is any way to self-reference the myfig structure using 'self' or something similar in the anonymous function, that would be optimal, but this is already pretty cool!Klystron
K
3

Refer to this link The answer to your problem could be this code (this will work with MATLAB R2014b and above). I tested with R2015a.

figure; spy;
my_fig=groot;
cnt = 0;
pause(0.05)
while ~isempty(my_fig.Children)
    cnt=cnt+1
    pause(0.01)
end

Here cnt value will be proportinal to the time, window exists before close. Note:

  1. One can reduce the argument values of pause and while counting time, pause time is to be taken into account
  2. Instead of cnt variable of counter method, one can use system clock time.
Kovno answered 3/2, 2018 at 17:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.