Question

I am using MATLAB for my data analysis. In my scripts I create figures with fit results so that I can quickly play with fit parameters and see how they change my end results.

My question is whether there is a simple way to be able to just refresh my figures along with subplots and annotations without losing the positions and sizes of the subplots and annotations. I.e.: I would like to be able manually position my figures on my workspace (I use Linux), manually adjust figure size/position, subplot sizes/positions and annotation sizes/positions and then have their content update, when I rerun the script that does my fitting.

I do realize that the command figure(...) does this nicely and it works, but I am having the problem, that when I resize/move subplots and move annotations, that they're sizes/positions get lost, when I rerun the script.

I am aware that I probably need to use the subplot/annotation handles for this but the question is, what the most elegant and simple way is to do this? Since I need the code to also work when run the first time (i.e. no figures/subplot/annoations yet existent), will I need a lot of if-clause, to check if the handles already exist?

I've been using MATLAB for quite some time and for almost equally long it's been bothering me that I don't know an elegant way to do this!

Was it helpful?

Solution

I had two ideas:

  1. use the "File > Generate Code..." functionality. MATLAB will create a function that recreates the figure with any modification you made interactively.

  2. manually retrieve the properties of interest for the objects manipulated and apply them again when you rerun your scripts. You could either maintain a list of handles for those graphics objects, or even use the 'Tag' in combination with the FINDOBJ function to locate such objects.

I will illustrate the latter idea with an example:

When the script is run for the first time, we give the user the chance to make changes to the figures interactively. Once done, we retrieve the 'Position' property of figures and all children components contained inside them. These values are then saved to a MAT-file.

Now the user adjusts some parameters and reruns the script. We check for the presence of the MAT-file. If it exists, we load the saved position values and apply them to the figures and their descendant objects, thus restoring the components to their last saved state.

This solution is rather simplistic, thus if changes are made to the script breaking the hierarchy of the graphics handles, you will have to delete the MAT-file, and run the script again.

%# close all figures
close all

%# your script which creates figures
figure, plot(rand(100,1))
figure
subplot(121), plot( cos(linspace(0,6*pi,100)) )
subplot(122), image, axis image, axis ij

%# check for MAT-file
if exist('script_prefs.mat','file')
    %# load saved values
    load script_prefs.mat

    %# get opened figures, and find objects with a position property
    fig = get(0, 'Children');          %# allchild(0)
    obj = findobj(fig, '-property','position');

    try
        %# apply values to position property
        set(fig, {'Position'},figPos);
        set(obj, {'Position'},objPos);
    catch
        %# delete MAT-file
        delete script_prefs.mat
    end
else
    %# get opened figures, and find objects with a position property
    fig = get(0, 'Children');
    obj = findobj(fig, '-property','position');

    %# wait for the user to finish customizing
    waitFig = figure('Menubar','none', 'Position',[200 200 200 40]);
    h = uicontrol('Units','normalized', 'Position',[0 0 1 1], ...
        'String','Done?', 'Callback','uiresume(gcbf)');
    uiwait(waitFig); 
    close(waitFig);

    %# get position property of figures and tagged objects
    figPos = get(fig, 'Position');
    objPos = get(obj, 'Position');

    %# save values to file
    save script_prefs.mat figPos objPos
end

OTHER TIPS

I take it you mean you want to refresh the plots themselves, but not anything else.

When you perform a plot(), specify an output argument to retrieve a line handle. Then, when you want to plot different, data, manually adjust that line handles' XData and YData:

lh = plot(xdata,ydata);

%# do some calculations here
...

%# calculated new values: newX and newY
set(lh, 'XData', newx, 'YData', newy);

This is likewise for anything else you want to refresh but not recreate - get the handle corresponding to the graphics object and manually update its properties at a low level.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top