Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab figure 'age'

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
like image 890
user2305193 Avatar asked Feb 03 '18 13:02

user2305193


3 Answers

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
like image 90
Yair Altman Avatar answered Nov 14 '22 19:11

Yair Altman


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;
like image 26
Tommaso Belluzzo Avatar answered Nov 14 '22 19:11

Tommaso Belluzzo


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.
like image 29
Chandra Avatar answered Nov 14 '22 21:11

Chandra