inconsistent behavior with "undocumented Matlab" figure handles - matlab

I read the blog post on assigning transparency to plot markers. I tried the code on a simple example and all was well. Then I tried a tight loop, plotting a single point at a time (doing this to assign a different color to each point in the graph), and invariably within a few loop cycles, when I grab the "plothandle.MarkerHandle", it's empty. In these cases, the class of this empty object is Matlab.graphics.GraphicsPlaceholder
while when the operation is successful, the class is:
matlab.graphics.primitive.world.Marker
The basic loop follows. colormatrix assigns a [r,g,b] color to each data point.
hold on
opacity = 0.5;
for jk = 1:numel(idx
tmph = plot(foox(jk),fooy(jk),'o','color',colormatrix(jk,:) );
tmpk = tmph.MarkerHandle;
tmpk.FaceColorData = uint8(double(tmpk.EdgeColorData).* [1,1,1,opacity]');
tmpk.EdgeColorData = uint8(double(tmpk.EdgeColorData).* [1,1,1,opacity]');
end
I've tried things like clearing variables every loop, putting in a delay timer, and so on, with no luck. I'm using Matlab R2015a.
EDIT: here's a simple example. What I seem to be finding is that if I run the entire script, it always fails. If I break it into two pieces where noted and execute the second section with a separate key stroke (ctrl-enter or selectall/F9 in the IDE editor), everything works. And yes, I'm aware that "undocumented features" are risky , but since MathWorks still hasn't figured out that allowing transparency -- and indexed color assignments -- are good things for the plot function, I'm still looking for a better workaround than using patch to draw each data point.
figure
xfoo = 1:10;
yfoo = 2*xfoo;
tmph = plot(xfoo,yfoo,'p','color',[1,0,1]);
hold on
opacity = 0.7;
% wait a while here.
tmpk = tmph.MarkerHandle;
tmpk.FaceColorData = uint8(double(tmpk.EdgeColorData).*[1,1,1,opacity]');
tmpk.EdgeColorData = uint8(double(tmpk.EdgeColorData).*[1,1,1,opacity]');

The fact that the script seems to work if you wait a bit between the plot and the retrieval of tmph.MarkerHandle suggests that you have the same issue that was reported on the blog by a user running R2014b. Yair suggested to call drawnow after the plot:
figure
xfoo = 1:10;
yfoo = 2*xfoo;
tmph = plot(xfoo,yfoo,'p','color',[1,0,1]);
hold on
opacity = 0.7;
drawnow;
tmpk = tmph.MarkerHandle;
tmpk.FaceColorData = uint8(double(tmpk.EdgeColorData).*[1,1,1,opacity]');
tmpk.EdgeColorData = uint8(double(tmpk.EdgeColorData).*[1,1,1,opacity]');
The workaround didn't work for a user running R2015a, which doesn't sound promising, but the fact that waiting seems to help for you, is encouraging.

Related

missing figure toolbar and possible change in global variables

Today i tried adding a slider below my graph, so different graphs would be drawn when you slide it. Eventually i got all of this to work perfectly fine, however i still have two small issues.
On top of the figure with the slider, the figure toolbar is gone. It can easily be added by clicking view -> figure toolbar at the top in the figure itself. However to do this everytime is a bit tedious. And when i google'd for the problem, the results where are all guides to create custom toolbars. I just want to add the default toolbar back, it was fine. But i do not know how to do that. Typing 'uitoolbar' gives an empty one. But i am not sure how to fill it with the default icons.
And the second problem i ran into;
The main script calls in the end for a function, this function then creates the new graph with the slider. However herefore i needed to transfer the matrix of data to plot from the main script to the function, so i made the matrix a global variable. However as soon as the function is called, matlab gives me this error (once for each global variable):
> In xxxx at 270
Warning: The value of local variables may have been changed to match the globals.
Future versions of MATLAB will require that you declare a variable to be global before you use that variable.
Before i call the function i type
global xL yL zL p
which are the data required to plot. Then the first line in the function file is this same line again. The data seems to be transmitted fine and the graph shows the correct plot.
Is this some error i can just ignore then? Since everything works as it should? Or what does it mean exactly?
Ok here are my 2 cents:
1) From what I understand the simplest way to fetch the toolbar would be using findobj and then make it visible:
hToolBar = findobj('Type','uitoolbar');
set(hToolBar,'Visible','on');
You can also get the toolbar's properties using "get". Here is what it looks like from a simple script I ran:
get(hToolBar)
hToolBar =
0.1890 %// don't worry about that number; it's the handle for the toolbar.
BeingDeleted = off
ButtonDownFcn =
Children = [1.18896]
Clipping = on
CreateFcn =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [1]
Selected = off
SelectionHighlight = on
Tag =
Type = uitoolbar
UIContextMenu = []
UserData = []
Visible = off
I don't know why it disappears though.
2) You might get rid of those global variables if you sent your data as inputs to your function is that a possibility?
For example:
function PlotData(xL,yL,zL,p)
%// Your code here
Hope that helps!

removing units from plot

I try to remove the Matlab-given units from this plot but I don't find a way:
figure(1)
hold on
set(gcf,'PaperUnits','centimeters',...
'PaperSize',[15 9],...
'PaperPosition',[0 0 15 9]);
pzmap(LB); sgrid; grid on; axis equal;
title('');
xlabel('\sigma [rad/s]')
ylabel('\omega [rad/s]')
hold off
After that commands the xlabel looks like this: \sigma [rad/s] (seconds^-1). The seconds comes with pzmap. How can I remove them?
I found, some strange behavour:
If generate code by the figure plot manager I get this:
% Create xlabel
xlabel('\sigma [rad/s] (seconds^{-1})','Units','pixels');
Why???
Now I get it - without pzmap/pzplot
pol = pole(sys)
figure(1)
plot(real(pol(:)),imag(pol(:)),'x')
title('');
xlabel('\sigma [rad/s]');
ylabel('\omega [rad/s]');
sgrid
pzmap is a high-level convenience function, but it's not the best choice for this (it's also stored in a folder of obsolete functions in R2013a, so it may get marked for official removal in the future). Instead, let's create an example plot using pzplot directly instead of pzmap. This is still a plot function that does a lot under the hood, but it returns a handle, h, to the plot:
sys = rss(3,2,2);
h = pzplot(sys);
sgrid;
axis equal;
We can via the options of a pzplot with getoptions:
p = getoptions(h)
To set the labels and units as you desire, you might try this, using setoptions:
p.Title.String = '';
p.XLabel.String = '\sigma';
p.YLabel.String = '\omega';
setoptions(h,p);
I believe that the units of 'seconds-1' that the plot displays is equivalent to the 'rad/s' that you want to specify. I know that the two look is very different (I prefer being specific about radians myself), but that's a disadvantage of using such a plot function that tries to do everything for you. If you wanted to remove the default string or add another option, you'd likely have to do some low level hacking. An easier way around, might be to use the "Generate Code..." command ("Generate M-File..." in older versions") under the "File" menu in the figure's toolbar and edit the plot labels there (there's also a programmatic option for this on the File Exchange). Or you could output to postscript and edit that.
Alternatively, you can use pzoptions to create a list of options to pass to pzplot or pzmap (undocumented in the latter case):
p = pzoptions;
p.Title.String = '';
p.XLabel.String = '\sigma';
p.YLabel.String = '\omega';
sys = rss(3,2,2);
pzplot(sys,p);
sgrid;
axis equal;
You'll see that that for some reason the text size is much smaller in this case. pzplot and pzmap must set the font size to 10 themselves. You could easily do this.
Fore more on customizing this and related Control toolbox plots, see this article.
After intense low-level digging, there is actually a pretty simple way to override the default behavior.
p = pzplot(sys);
p.AxesGrid.XUnits = 'rad/s';
p.AxesGrid.YUnits = 'rad/s';
Changes appear to take effect immediately. I have even tried setting the value to nothing, i.e.
p.AxesGrid.XUnits = '';
and it effectively removes the annoying parenthesis with the units. Technically, matlab creates a custom-class element they store under the name AxesGrid in the resppack.mpzplot class instance, with some standard LTI-behavior. You can probably work around some stuff by "injecting" a script with the same name as one of the standard library functions, so that it will be called instead, and change things in there, but this is the closest I have come to removing those annoying units in a few lines.
As a side info, the AxesGrid object is initialized in
...\controllib\graphics\#resppack\#pzplot\initialize.m
should you want to check it out.

MATLAB: Making a video using writeVideo

I am currently trying to make a video using the writeVideo function in MATLAB. I have made a GUI using GUIDE which includes a slider, a few checkboxs, and a single axes (tagged as axes1). When I move the slider, the axes will plot certain shapes that change according to the slider value.
What I am trying to do is record a video of the GUI being used to show the functionality in a presentation. However, when I play back the video (after making it using writeVideo), it shows the slider value moving and the checkboxes being checked correctly, but the plot never changes (i.e. it will only show the original shape). This seems to be some refresh error, however, anything I have tried has not worked (refresh, drawnow, etc.)
Any idea why this is happening? The following is the code I am trying to implement:
vidObj = VideoWriter('test.avi','Motion JPEG AVI');
open(vidObj);
flag = 0;
if flag<12 %movie will be 12 frames long
flag = flag+1;
if slider<1
plot something...
elseif slider>=1 && slider<2
plot something else...
etc...
elseif slider<=5
plot something else...
end
hFigure = findobj('Name','gui');
currFrame = getframe(hFigure);
writeVideo(vidObj,currFrame);
clear hfigure currFrame image;
else
fprintf('done\n')
close(vidObj);
end
As stated, I can then use implay to play back the test.avi file, however, the plot never updates.
Thanks in advance
Note: I am using MATLAB R2012b
EDIT:
The following is how I ended up creating my video: maybe this will help someone who was facing similar issues to the one stated above.
I basically gave up on using getframe and decided to 1) get screenshots, then 2) turn the screenshots into a movie. To get the screenshots, I first ran my program then, in the command window, invoked the following code using the java toolkit
i = 1;
while true
robo = java.awt.Robot;
t = java.awt.Toolkit.getDefaultToolkit();
%# Set screen size
rectangle = java.awt.Rectangle(0,0,1000,640);
%# Get the capture
image = robo.createScreenCapture(rectangle);
%# Save it to file
filehandle = java.io.File(sprintf('capture%d.jpg', i));
javax.imageio.ImageIO.write(image,'jpg',filehandle);
pause(.4) %# Wait for 0.4 seconds
i = i + 1;
end
This then continually ran in the background and took snap shots of the screen and stored them into the current directory. to stop it from running, just use Ctrl C. Once I had the screen shots, I used the following code to create the movie:
vidObj = VideoWriter('test.avi','Motion JPEG AVI');
open(vidObj);
for i=7:87 %these are the frames I wanted in my movie
x = num2str(i);
im = horzcat('capture',x);
im1 = horzcat(im,'.jpg')
imdata = imread(im1);
writeVideo(vidObj,imdata);
end
close(vidObj);
getframe is sometimes problematic. I'm not sure I can give an answer, and I can't simply comment because of my reputation, but this link might be of help. After you get the figure from the GUI, turn it into an image and then into a frame. Worth a shot.
If you change your monitor settings to 16 bit color it will solve the problem you are having. This has been documented on the link provided. My previous answer was deleted because I only supplied the link and told you how to solve the problem (sorry) but if you actually click on the link and see what they say or change your monitor settings to 16 bit color everything will work. From the link you can see that people have had this problem since 2009 but it was updated in april 2013 so it is still a problem and changing your monitor settings to 16 bit color is still a solution.
Hope this helps!
http://www.mathworks.com/matlabcentral/newsreader/view_thread/257389

Why is a plot handle always invalid?

I want to delete a plot and its colorbar ( actually I want to delete everything in a plot, but that seams to be almost impossible, see make axes invisible or delete plot completely)
I do this:
In the plot
hplot = pcolor(xAxis, yAxis, Data2D);
hcb = colorbar;
handles.image.hColorbar = hcb;
handles.image.hplot = hplot;
guidata(handles.output,handles);
later in the gui:
if (isfield(handles,'image') && isfield(handles.image,'hplot'))
if (handles.image.hplot~=0)
delete(handles.image.hplot);
delete(handles.image.hColorbar);
handles.image.hplot = 0;
end
end
It works for delete(handles.image.hplot) but fails for handles.image.hColorbar with invalid handle - why?
This snippet works fine here...
In general, it is advisable to check for ishandle() on both objects, so that you don't have to set handles.image.hplot = 0. Since delete has made the handle invalid, it will never pass the ishandle check until you re-assign a new, valid handle to it.
If the code doesn't pass the ishandle() tests, it means it was deleted already, so no need to delete it again.

Matlab IMRECT backward compatibility

I've writtend a GUI function in MATLAB R2009b which makes use of the IMRECT function. I need to make sure this GUI also works in MATLAB R2007b: since this release the IMRECT function has undergone extensive changes. I have two question:
1 - in the new (R2009b) IMRECT, a method GETCOLOR is defined which allows to get the color which was selected by the user using the scroll menu. Is there a way to mimic this behavior for the old (R2007b) function?
2 - in MATLAB R2009b I can use WAIT after using IMRECT as follows:
h = imrect(axhandle);
wait(h);
this allows to wait unitl the user as correctly placed his/her rectangle and has double click to confirm the choice. Is there anything analogous that can be used with IMRECT from R2007b?
Unfortunately, you need a workaround for both functions.
Here is one way to do it:
%# Create a figure and some points
fh = figure;plot(rand(10,1),rand(10,1),'.')
ah = gca;
%# this allows the user to place the rectangle. However, the code resumes
%# as soon as the rectangle has been drawn
rh = imrect(ah,[]);
%# Create a dialog to have the possibility to uiwait
wh = warndlg('Please close this dialog once you are done adjusting your rectangle');
uiwait(wh)
%# Get the color of the rectangle
rectKids = get(rh,'Children');
rectangleColor = get(rectKids(1),'Color');
You can use verLessThan to check for the Matlab version in order to get the proper functionality. However, if there are users who'll use the code both on 2007b and 2009b, I suggest you leave the dialog box in for everyone, so that they don't get confused when they switch.