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')
Related
I'd like to call the cftool from a function/script, do my fitting, store the variables to the workspace and then resume execution of my function. Naively, one could assume that assigning a handle to the GUI and then using waitfor(), like for a graphics object, would do the job, but that was a bit short-sighted.
Minimally this reads
h = cftool;
waitfor(h);
disp('happy fitting');
and of course does not work.
Cheers.
The cftool does not return a handle, so you need to search for it using findall:
cftool
f = findall(0,'Type','Figure');
waitfor(f(1))
disp('Happy fitting!')
If you have multiple figures f may have multiple values and it could cause some issues. So keep track of your figures and check which position has the gui handle, before you call waitfor.
I have a .m file (script) that is controlling a real-time robot.
What i do within this file is:
1- find a trajectory
2-infinite loop:
read from robot
update robot
plot some stuff (basically I'm drawing a new point in each iteration that represents the position of the robot in a previously opened map, it's updating the map)
end of loop
What I want to do is to create a GUI that allows me to make the plots and see some values that the robot returns at the same time, in real time.
From what I read, MATLAB can't run both a script and a GUI at the same time.. I can make it plot in real time in the GUI but I can't seem to be able to update the values returned by the robot in text boxes in GUI..
Do I have to put it all in the same file or is there a way for the GUI and the script to work in separate files?
Thank you in advance!
MATLAB has not trouble running both. I don't know where you read that but it's not true; MATLAB is not the best tool to solve this problem, but it can do it.
First, I'm going to frame your problem in code, to make it easier to solve. Your question is vague and general, so my response has to be be general as well. I'm making some assumption about your function structure, but it really should look a lot like this:
endflag = 0;
while ~endflag
robotData = getRobotData(robotHandel);
derivedData = doStuffWithData(robotData);
updateRobot(derivedData);
showData(robotData, derivedData)
endflag = checkEndFlag(robotData, derivedData)
end
So, your problem is the showData functionality. What it should do, is determine which values need to be displayed from it's inputs, and pass those to your GUI. Like so:
function showData(robotData, derivedData)
guiInputData = dataParser(robotData, derivedData)
YourGUIFunctionName(guiInputData)
end
The GUI function should then build itself using those inputs. Any GUI function working that way, will do what you want it to. If you want a more specific solution, you need to give me more specific information about your problem. Good luck, I hope this helps.
Problem
I am running a Matlab script that creates a mesh geometry stored within a ‘.m’ file; all of this is for running with a finite element solver. I give it a number of elements, and it creates a mesh of quadrilaterals that fit within a boundary; two examples of the geometry are shown in Figure 1 and Figure 2. When I use it for only a single number of elements, it works great. On the other hand, when I try to use the mesh-generating script within a loop, varying the number of desired elements (n = 1,2,4,...32,64), the file reads as though I just ran it at n = 1. It’s as if the ‘.m’ file was not rewritten.
Figure 1. Mesh with 10 quadrilateral elements.
Figure 2. Mesh with 40 quadrilateral elements.
Current Approach
for i = 1:4
n = 2^i % n stores the desired number of elements (2^i is only an example)
% Check if '.m' file exists in current directory
allFiles = dir(currentFolder)
allNames = {allFiles.name}
check = ismember('p4.m',allNames);
% If so, delete the file
if check
delete 'p4.m'
end
% Create the 'p4.m' file
p4Mesh(n)
end
p4Mesh Function Summary:
function p4Mesh
close all;
inputfile = 'p4.m';
% open file
fid = fopen(inputfile,'w');
fprintf(fid,'MESH CODE HERE')
% Close file
[st] = fclose('all');
end
Summary
The p4 function definition might be getting cached so you're not picking up the new versions you write out to disk on subsequent calls to p4(). Use clear p4 to drop the cached definition and force it to re-read p4.m each time you update it.
Details
You may be running in to an issue with Matlab's function definition caching. When you call a function or class for the first time, Matlab reads the definition in from the .m file on disk, compiles it, and runs it, and then keeps that compiled definition cached. It's pretty unlikely that the file writing is lagging the Matlab loop, since fopen/fprintf/fclose are synchronous, and Matlab is single-threaded. But Matlab's function-loading mechanism might not be noticing the changes on disk as fast as you need.
Matlab will re-read the function definition if it notices the definition has been changed on disk. If you save a function file from the Matlab Editor, it notices the change right away since that goes through Matlab. But if you write the file's contents from code, it looks to Matlab like an external change. Matlab gets updates about these changes in a system-dependent manner, like getting file change notification events from the operating system, or periodically polling the filesystem to check file timestamps. See doc changeNotification and doc changeNotificationAdvanced for details on this.
Since you're re-writing the file in a tight loop, the updates might be happening too fast for Matlab's change notification to notice. In fact, Matlab may delay the file update checks until it's done running user functions (for performance and consistency reasons), so might not do the update checks at all until it's done with your loop and returned from that script to the command line. In this case, if you called p4() multiple times inside the loop, it would use the cached function definition from the first pass each time, and you'd see the same output from the function. This sounds like what you're describing.
Diagnosis
To see if this is what is actually happening, examine the contents of the p4.m file on disk outside the mechanism of calling it as a Matlab function. You can use the md5sum program available on many systems to output a one line checksum of it. Or you can call out to cat or just re-read it using fopen/fread/fclose and print it or an md5 checksum of it to the console from within Matlab. If the file looks different on disk each pass, but you're getting the same output from calling p4(), it's probably function caching.
Fixing
You can force Matlab to re-read a function from the current .m file on disk by using the clear command to drop its cached compiled definition from memory. In this case, do a clear p4; in each pass of the loop right after you've called p4mesh to write out the p4.m file, and before p4 gets called again.
Doing pause or drawnow inside the loop may also give Matlab's function-caching mechanism a chance to notice the updated .m file on disk. But clear p4 should be more reliable and deterministic, since it forces a re-read each time.
In the long run, it might be better if you could get your professor to give you a p4mesh that produced .mat data files instead of .m function definition files, like the commenters suggested. The .mat data files are more suited to rapidly changing definitions, and don't have this caching issue.
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.)
I am tasked to design a GUI and I need to use variables and plots from a different mfile which I created earlier. I'm pretty confident about getting variables from the processing mfile but I'm not sure how to get the plots/figures.
So basically my question is whether I can get() a figure from my mfile and then set() an axes to that figure inside my GUI.
Note: The reason I am doing this is because I want to keep the processing of data separate from the GUI mfile. I could just dump all the processing in the callback of my process button but that's not good. I would also appreciate good coding practices for my case since I have never worked with GUI's before (only scripting with PHP and MATLAB)
Note2 (rundown of what has to be done): In the GUI we basically are supposed to load 2 files, we then press the "process" button and then 4 plots have to appear. All the processing code already exists in a previously written mfile (by me).
Thanks! :)
I figured it out myself! What I did was use gcf to get the current figure like so: output.worldmap = gcf I then passed the object back like so: setappdata(0,'output',output) and grabbed it again inside my callback function like so: getappdata(0,'output') and used the following function to set the axes set(output.worldmap,'CurrentAxes',handles.axes_worldmap) I also made sure that the correct axis was set before I actually ran my mfile which does the processing with axes(handles.worldmap)