How to reproduce figure through a previously saved figure handle? - matlab

I plotted the distribution of a set of data in a 3d scatter plot.
h = scatter3(D1,D2,D3,'.');
I have saved h but now need to reproduce the graph. What function should I call on h so that I can get the graph without recalculating D1, D2, D3? Because D1, D2, D3 are computationally expensive to re-calculate, I don't want to do it every time when I need a graph.

"Recreating a graph" can be done if you have the following information:
The data used to create the graph
The graph type used
Any optional settings (colors, axes, scaling, orientation, ...)
The "handle" of a graph (or figure) points to the memory where all that information is stored - but it's just a pointer. Unless you save "what is pointed to", it is no use to you. There is a very cool way to achieve this with a single command. After you have created a figure, you can simply type
saveas(gcf, 'myLastGraph.m', 'm');
Instead of gcf ("get current figure" - the handle to the most recently selected figure) you can use whatever the handle is of the graph you want to save (which must still be visible) - for example, h in your code sample. This will create two files in your current directory (if you specify a full path in the second argument, it will create the files in that directory instead):
myLastGraph.fig
myLastGraph.m
Now you can close all your graphs, clear all variables. Next, you can simply run
myLastGraph
from the command line - and your graph will be re-created, using the data that was saved on disk.

If the graph is still open, you can get the Xdata, Ydata and Zdata by using:
XYZCell=get(get(get(h,'currentaxes'),'children'),{'xdata','ydata','zdata'});
Or if you don't want a cell:
XData=get(get(get(gcf,'currentaxes'),'children'),'xdata');
YData=get(get(get(gcf,'currentaxes'),'children'),'ydata');
ZData=get(get(get(gcf,'currentaxes'),'children'),'zdata');
If the graph is closed, h is useless - as far as I'm aware there is no way to reform a graph from a closed figure handle.
Why not use save your variables first?
I1=d1;
I2=d2;
I3=d3;
scatter3(d1,d2,d3,'.');

By "computationally expensive to re-calculate" I'm not sure whether you mean calculating values of D1, D2, D3 or plotting those values. If the calculation is intensive, save the values to the workspace or save them to disk (e.g. print to a file) so you can load them again later for plotting. You can also save the graph as a *.fig file, which you can open and edit later, which might be a good choice if the plotting is the slow part.
There's no way I know of to use the handle (h) to get your data back, once you've closed the window.
With the figure window still open, however, you can use h to pull in the data:
xyzData = get(get(h, 'children'), {'xdata', 'ydata', 'zdata'});
(NB: h = scatter3(D1,D2,D3,'.'); sets h as the handle to the scattergroup. #Hugh Nolan's fine answer requires that h be the handle to the figure.)

Related

How to control the figure which appears in bayesopt function?

bayesopt draws figures like this:
How to access such figures in order to modify title or something? If I use gcf it is not guaranteed I get the correct figure because I could change focus to another figure window during execution.
Apparently bayesopt does not allow you to return a figure handle. So I suggest that on the line directly after your call to bayesopt you call h=gcf;, thus forcing your program to return the figure handle to h, which can then be modified at any desired time, even when moving to other figures.
results = bayesopt(fun,vars,Name,Value); % execute bayesian optimisation
h = gcf; % directly after optimisation grab a figure handle
Now you can modify properties in h, e.g. for the title you'd simply do
h.CurrentAxes.Title.String = 'Your plot title'
The reason this works is that MATLAB does not display figures until the full code has finished running. At least that's the case for my script, where I generate a figure, perform a few minutes of optimisation, then generate another figure. Both figures get displayed at the same time, i.e. when MATLAB has finished running the full program. There's thus no way you can click other figures when the code is running, since they are simply not there. If you happen to have older figures open (from other scripts), focus gets shifted to the latest created figure anyway, the moment it's created in the code (so not when it's displayed), thus you'd need to click a figure in the few milliseconds between the bayesopt call finished and the gcf call, which I'd say is so improbable that it's not worth considering, especially since it requires manual intervention.
As was pointed out in comments by Cris Luengo and Dev-iL, the figures are tagged and can thus be found using findobj:
h1 = findobj(0,'tag','bayesopt.MinObjective')

Update gramm plot matlab crashing

I have a MATLAB GUI that calls an external function to make a plot (make_ethogram_plot).
The idea would be to have an external figure that is constantly updated with the output value from the figure. Every time the data gets updated it should replot the values, it updates at ~10 Hz. I chose gramm (https://github.com/piermorel/gramm/tree/master/%40gramm) because it is really easy to make a raster plot.
This is the function that gets called. I am having issues to
1) Make it only update in the parent figure with specific name, instead of plotting in the GUI(which is the active figure).
2) Make it not crash. It would open many figures or open or close the same figure at 10 Hz until crashing.
In this configuration, it gives error because it doesn't find g after the first plot. Making g , f, and p1 globals makes it crash (opens every time it gets called)
function make_ethogram_plot(datastructure)
% if the figure doesn't exists create it
if(isempty(findobj(0, 'Name', 'My_gramm_ethogram')))
f=figure('Name', 'My_gramm_ethogram');
p1 = uipanel('Parent',f,'BackgroundColor',[1 1 1],'BorderType','none');
g = gramm('x', datastructure.final_data.frameID, 'color', categorical(datastructure.final_data.behavior));
g.geom_raster();
g.set_parent(p1);
g.draw()
else
% defining f,p1, g here (or having them global) works but crashes
% due to refresh rate
g.update()
end
end
I wrote this code to try to replicate your problem:
function animate_random_data
N = 10000;
data = [cumsum(rand(N,1)),randn(N,1)];
for ii=0:1000
% Plot the data
make_ethogram_plot(data);
drawnow
% Compute new data
data(:,1) = cumsum(rand(N,1));
data(:,2) = randn(N,1);
end
function make_ethogram_plot(data)
fig = findobj(0, 'Name', 'My_gramm_ethogram');
if(isempty(fig))
% If the figure doesn't exists create it
fig = figure('Name', 'My_gramm_ethogram');
ax = axes(fig);
plot(ax,data(:,1),data(:,2));
drawnow
set(ax,'xlimmode','manual','ylimmode','manual');
else
% If it does, update it
line = findobj(fig,'type','line');
set(line,'xdata',data(:,1));
set(line,'ydata',data(:,2));
end
Here, I followed your concept of looking for a named figure window, and creating one if it didn't exist. However, if it does exist, I simply replace the XData and YData property of the line that is already there. This is the fastest way of animating a graph, much faster than deleting the existing plot and creating a new one. After plotting, I use drawnow to update the display. I set XLimMode and YLimMode to manual to prevent re-computation of axes limits and consequent re-drawing of the axes.
The function took 17 seconds to draw all 1000 frames, meaning it's drawing about 60 frames a second. It does not (and should not) crash MATLAB.
You can limit the display rate to 20 frames/sec with drawnow limitrate. It will skip updating the display if the frames come too fast.
I don't know what the gramm/update method does, the class is too complicated to quickly see what is going on, but I dare presume it deletes the axes and creates a new plot from scratch. Not that this should crash MATLAB, it might be worth while to submit a bug report. However, you would probably want to update the figure in the more efficient way, following the method I demonstrated above.
Note that this method can be used to update any of the graphical elements in a plot. For example, I have used this method to animate images.

How to open desired figure by dialogue box in MATLAB

Is there any possible way to open the desired figures from a lot of plotted figures in MATLAB?
If it is possible with dialogue box then it will be perfect.
I have like 75 figures plotted after my code but I have closed the figures at end of loops as they are too much.
Is it possible to open just one figure by just entering values necessary for plotting figure in MATLAB at end of program?
One way to do this is the following:
1) You save the figures as .fig in a dedicated folder using the saveas command, e.g.:
saveas(gcf,['FileName_',num2str(idx),'.fig']);
where idx is the index associated with the figure number (so in 75 in the example you mentioned). For simplicity, I would save all of them in one folder.
2) You use inputdlg to create an input dialog box, where you type in the index you want. Then, you run uiopen(['FileName_',idxFromInput,'.fig']), which will display the figure. Note that the output from inputdlg is normally a string, so you don't need num2str here.
From Wikibooks: MATLAB Programming/Handle Graphics (emphasis mine):
Every time you close a figure, either by using the close function OR by hitting the 'X', you can no longer access the data, and
attempts to do so will result in an error. Closing a figure also
destroys all the handles to the axes and annotations that depended on
it.
This means that once you close your 75 figures, they are gone for good.
I would suggest saving all your figures to .fig file format, because this will allow you to open them later in MATLAB.
Take the following example:
x = linspace(0, 2*pi); % Sample data.
for i = 1:3 % Loop 3 times.
h = figure; % Create figure window and capture its handle.
plot(i*sin(x)); % Plot some data.
saveas(h, sprintf('fig%d.fig', i)); % Save figure to .fig file format.
close(h); % Delete the figure.
end
Now you can tell MATLAB to open one of the figures using the openfig function. For example, let's open the second figure fig2.fig. Go to the Command Window and type openfig('fig2') (including the .fig extension in the file name is optional).
>> openfig('fig2')
ans =
Figure (1) with properties:
Number: 1
Name: ''
Color: [0.9400 0.9400 0.9400]
Position: [520 371 560 420]
Units: 'pixels'
Show all properties

Save Figure generated from HeatMap() from Bioinformatics Library - Matlab

I would like to save the image I generate the HeatMap() function from the bioinformatics library.
I cannot figure out to have the image without manually exporting the data.
I'd prefer to use HeatMap over Imagesc because it automatically scales the data to the mean.
I do not have the Bioinformatics Library for matlab, However you should be able to get the current figure with the function gcf. It is not the most stable way, but in most cases this will work excellent. Then you can save the figure as a figure or image with saveas.
HeatMap(...);
hFig = gcf;
saveas(hFig,'myName','png'); % You can use other image types as well and also `'fig'`
There is a second way as well. The HeatMap class also contains a plot method. This method may return the figure handle to the HeatMap plot then save the image with saveas.:
hHM = HeatMap(...);
hFig = plot(hHM);
saveas(hFig,'myName','png');
I share a part of a Matlab code that I used when I analyzed some data from TCGA
#I was considering two gene expression level taken from cancer disead tissue and
# healthy tissues comparing them with this Heatmap
labela=Gene;
labelb=Gene2;
data1=[dataN(indg,:) dataC(indg,:); dataN(indg2,:) dataC(indg2,:);];
H=HeatMap(data1,'RowLabels',
{labela,labelb},'Standardize','row','Symmetric','true','DisplayRange',2);
addTitle(H,strcat('HeatMap',project));
addXLabel(H,'patients');
addYLabel(H,'geni');
#I have allocated the plot in a variable
fig=plot(H);
# Then I saved the plot
saveas(fig,strcat('D:\Bioinformatica\Tesina...
Prova2\Risultati_lihc\',dirname,'\HM.fig'));
But if you have to run one single object I advise against waisting your time in writing code (even if it is always a good thing to explore and strengthen your knowledge), I used because each time I was running a pipeline. Otherwise you can go on
1)File ----> Export Setup
2) Export
3)Save in the format you do want!

MATLAB query about for loop, reading in data and plotting

I am a complete novice at using matlab and am trying to work out if there is a way of optimising my code. Essentially I have data from model outputs and I need to plot them using matlab. In addition I have reference data (with 95% confidence intervals) which I plot on the same graph to get a visual idea on how close the model outputs and reference data is.
In terms of the model outputs I have several thousand files (number sequentially) which I open in a loop and plot. The problem/question I have is whether I can preprocess the data and then plot later - to save time. The issue I seem to be having when I try this is that I have a legend which either does not appear or is inaccurate.
My code (apolgies if it not elegant):
fn= xlsread(['tbobserved' '.xls']);
time= fn(:,1);
totalreference=fn(:,4);
totalreferencelowerci=fn(:,6);
totalreferenceupperci=fn(:,7);
figure
plot(time,totalrefrence,'-', time, totalreferencelowerci,'--', time, totalreferenceupperci,'--');
xlabel('Year');
ylabel('Reference incidence per 100,000 population');
title ('Total');
clickableLegend('Observed reference data', 'Totalreferencelowerci', 'Totalreferenceupperci','Location','BestOutside');
xlim([1910 1970]);
hold on
start_sim=10000;
end_sim=10005;
h = zeros (1,1000);
for i=start_sim:end_sim %is there any way of doing this earlier to save time?
a=int2str(i);
incidenceFile =strcat('result_', 'Sim', '_', a, 'I_byCal_total.xls');
est_tot=importdata(incidenceFile, '\t', 1);
cal_tot=est_tot.data;
magnitude=1;
t1=cal_tot(:,1)+1750;
totalmodel=cal_tot(:,3)+cal_tot(:,5);
h(a)=plot(t1,totalmodel);
xlim([1910 1970]);
ylim([0 500]);
hold all
clickableLegend(h(a),a,'Location','BestOutside')
end
Essentially I was hoping to have a way of reading in the data and then plot later - ie. optimise the code.
I hope you might be able to help.
Thanks.
mp
Regarding your issue concerning
I have a legend which either does not
appear or is inaccurate.
have a look at the following extracts from your code.
...
h = zeros (1,1000);
...
a=int2str(i);
...
h(a)=plot(t1,totalmodel);
...
You are using a character array as index. Instead of h(a) you should use h(i). MATLAB seems to cast the character array a to double as shown in the following example with a = 10;.
>> double(int2str(10))
ans = 49 48
Instead of h(10) the plot handle will be assigned to h([49 48]) which is not your intention.