I had some problems recently when I wanted to create an animated GIF mixing true color images and an overlaying graph.
I found a solution and thought I should share it!
The main problem is having a consistent colormap throughout the GIF. The rgb2ind function needed totransform the true color image to an indexed one provides a different color map for each frame. This will give weird colors in the GIF  because the indexing of the colors is right, but the associated colours change with each frame.
My solution is to make one large mosaic by repeating the background image and placing the overlays on top. Only then, then the rgb2ind function is called, so that it builds a colormap for all the colors of all the frames. Then you just need to cut it out and build the frames.
Here we go!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
% Gif file name here
gifName = 'd:\gif with different colormaps.gif';
 
% Prepare a figure and make it nice
hFig = figure;
hAxis = gca;
set(hFig,'color','w');
set(hAxis , 'Position' , [0 0 1 1]);
box(hAxis , 'off');
 
% Load a background image
I = imread('peppers.png');
 
 
% Prepare a few random overlays, one each frame of the GIF
n_frames = 5;
overlays = cell(n_frames);
for k = 1 : n_frames
    overlays{k} = rand(5);
end
 
 
% Coordinates where the overlay is plotted
s = size(I);
overlayCoord = [1+s(2)/5/2  ,  s(2)-s(2)/5/2  ,  1+s(1)/5/2   ,  s(1)-s(1)/5/2];
 
for k = 1 : n_frames
 
    % Cyclically select all overlays and paint
    hold off;
    imagesc(I , 'Parent' , hAxis);
    hold on;  axis equal;
 
 
    % Plot overlay over the image and make it transparent
    hOverlay = imagesc([overlayCoord(1) , overlayCoord(2)] , ...
                       [overlayCoord(3) , overlayCoord(4)] , overlays{k});
    alpha(hOverlay , 0.5)
 
 
    % Recover the figure contents and add it to the mosaic
    f = getframe(hFig);
    s = size(f.cdata);
    mosaic(: , (k-1) * s(2) + 1 : k * s(2), :) = f.cdata;
 
end
 
% Transform the whole RGB mosaic in an indexed image
[mosaic , map] = rgb2ind(mosaic,256); 
 
% Build frames for the GIF
frames = uint8(zeros(s(1) , s(2) , 1 , n_frames));
for k = 1 : n_frames
    frames(:,:,1,k) = mosaic(: , (k-1) * s(2) + 1 : k * s(2), :);
end
 
 
% And finally, save animated GIF
imwrite(frames , map , gifName , 'DelayTime' , 0.5 , 'LoopCount',inf);

And here is the result in all its random splendor:
gif with adapted colormaps

Category: Matlab | Leave a Comment

That’s an easy one. What we want is to press a keyboard key and have Matlab perform an action.

First, create a KeyPress function with two inputs, key and handles:

1
2
3
4
function handles = KeyPress(key,handles)
	if strcmpi(key,'r') % detect ‘r’
		% perform some action
	end

Note that I used the strcmpi function, which is case insensitive (so you do not have to worry if caps lock is activated).

Then, just put these two lines in the KeyPressFcn of your GUI.

1
2
3
4
5
6
7
8
9
10
function My_GUI_KeyPressFcn(hObject, eventdata, handles)
% hObject    handle to My_GUI(see GCBO)
% eventdata  structure with the following fields (see FIGURE)
%	Key: name of the key that was pressed, in lower case
%	Character: character interpretation of the key(s) that was pressed
%	Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles    structure with handles and user data (see GUIDATA)
 
	handles = KeyPress(eventdata.Key , handles);
	guidata(hObject, handles);

You might want to add these lines to the KeyPressFcn of some other controls as well; listboxes, for instance. This way the keyboard shortcut works also if the control has the focus. Do not put them in editable controls (such as Edit)!
I pass the handles to the KeyPress function as it is often useful. If you do that, do not forget calling guidata after KeyPress to update the variables!

Category: Matlab | Leave a Comment

I had a bit of a struggle with Matlab to do a relatively simple task: I wanted to click on an edit uicontrol displaying a number, and increment the number using the mouse wheel. Not as straightforward as it seems.
First, only the main window exposes a WindowScrollWheelFcn that is called when the mouse wheel is used. Second, edit uicontrols do not get the focus when you click on them, so when WindowScrollWheelFcn is called you cannot know which control raised it. Third, edit uicontrols call the ButtonDownFcn function only if you right click on them or left click on a 5 pixel border!.

To solve this problem we will use the hidden Java callbacks of the uicontrol, so go ahead and download the findjobj function if you don’t have it already.

I will now create a basic GUI with an edit uicontrol called edit1. Set the String property of edit1 to 1 (or any other number):

First, we will assign a more comfortable ButtonDownFcn to the edit1 uicontrol in order to detect clicks. Write the following lines in your figure’s OutputFcn:

1
2
3
4
5
6
% Assign a new callback function to the click event of the edit1 control
% It won’t work if you put it in your opening function since when 
% the opening function is called, the java objects have not been created yet!
 
set(findjobj(handles.edit1), ...
'MouseClickedCallback',{@MyButtonDownFcn , handles.edit1});

Then, create the following function:

1
2
3
4
function MyButtonDownFcn(hObject, eventdata,h)
% Manually assign the focus to the edit1 uicontrol
 
uicontrol(h)

Finally, create the WindowScrollWheelFcn for you figure, where we will check which control had the focus when the mouse wheel was turned and act accordingly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function figure1_WindowScrollWheelFcn(hObject, eventdata, handles)
 
h = gco;
if ~(h == handles.edit1); return; end % exit if edit1 does not have the focus
 
s = str2double(get(h , 'String'));
if isnan(s); return; end; % exit if edit1 is empty
 
% VerticalScrollCount is positive or negative depending on 
% the direction of the rotation. It can also change in value 
% depending on the rotation speed.
if eventdata.VerticalScrollCount > 0
increment = -1;
else
increment = +1;
end
 
% Change the value of the edit1 string
set(h , 'String', num2str(s + increment));

There you go! Now you can click on the edit uicontrol and change its value with the mouse wheel!

Category: Matlab | Leave a Comment

Matlab often sets the background color of GUI elements as the standard windows colors, which may be different on different PCs. This leads to this unaesthetic result:

aa

(notice how the frames have different backgrounds than the main figure)
The simplest way to solve this is to manually set the BackgroundColor property of each object. A more rapid way, however, is to define a SetBackgroundColor function (which will be called by your OpeningFcn) which looks for each component you might have in your GUI and changes its BackgroundColor:

function SetBackgroundColor
% This funtion changes the color of different UI controls
% and the toolbar in the current figure
% Claudio Vergari – http://claudiovergari.com
 
    c = [179 , 199 , 255] / 255;                        % RGB  background color
 
    % Find all objects
    Objects = [findobj('Style', 'checkbox') ;
findobj('Style', 'frame') ;
findobj('Style', 'text') ;
findobj('Style', 'radiobutton') ;
findobj('Style', 'pushbutton') ;
findobj('-regexp', 'Tag', 'uipanel') ;
];
 
    set(Objects, 'BackgroundColor', c);   % Set objects’s background color
    set(gcf, 'Color', c);                 % Set figure’s background color
end

This will nicely color your GUI but leave the toolbar gray, since toolbars don’t have a BackgroundColor property (up to Matlab 2010b, at least). The solution is a rather mystical undocumented feature, which can be added to the SetBackgroundColor function:

    Jcolor = java.awt.Color(c(1), c(2), c(3));    % Java background color
 
    hToolbar = findobj(gcf, 'Type', 'uitoolbar');    % Find all toolbars, if they exist
    if isempty(hToolbar);    return;    end;          
 
    jToolbar = get(get(hToolbar, 'JavaContainer'), 'ComponentPeer');
    jToolbar.setBackground(Jcolor);

There you go! (you might want a more sober color…)

Matlab GUI toolbar color

Category: Matlab | Leave a Comment

Here’s a basic Matlab tricks which might speed up your work.
There are plenty of ways to compute the global mean of an nxn (or even multidimensional) matrix; however the most compact is probably the following:

n = 5;
x = rand(n,n);  % a random nxn matrix
 
m = mean(x (:))   % global mean

The colon operator, in this instance, returns all the elements of x regarded as a single column. Of course the same thing can be done with the max and min function [min( x(:))].
When there are NaNs involved, the mean function returns a NaN. A simple way to calculate the global mean without considering the NaNs is:

n = 5;
x = rand(n,n); % a random nxn matrix
x( rand(n,n) > 0.5 ) = NaN; % add some NaN
 
m = mean (x (~isnan(x))) % mean without the NaNs

Actually there is a function in Matlab’s Statistical Toolbox called nanmean. It works exactly like mean (i.e., it returns the mean of each column) but without considering the NaN, so you can use nanmean(x(:)). However, if you don’t have the toolbox, you can create your own anonymous function:

nmean = @(x) mean(x( ~isnan(x) ));
m = nmean(x);

Last, if you have Inf or –Inf values, the mean will be affected by them. To calculate the mean excluding infinite values you can use this:

m = mean(x( isfinite(x) ));

Category: Matlab | Leave a Comment