MATLAB GUIDE slider position and radio buttons - matlab

I am trying to write a script that utilizes GUIDE to visualize some results and I have stumbled to some problems. I am going to describe the task first (I will try to make it as general as possible so the question is not too long).
I have a script (main1.m) that graphs a plot and then I pick an area of the plot to analyze (I will call it point1 from now on) and produce several plots through GUIDE (guide_fun1.m). The function guide_fun1 contains 2 radio buttons (created as a group) and a slider on the x axis so the user can see the plot for a smaller range if they wish (the plots initially are from 0 to 1 on the x axis but if the user wants to see from 0 to 0.6 the slider enables them to do so).
I am showing the code main1.m (it is not in detail in order to make it short but to demonstrate what I am trying to achieve) and the guide_fun1.m below. As you see main1.m is interactive and the user can continuously click on several points of the plot until they type exit to finish the program. For every point (point1) they click, a GUIDE window with several options for graphs and plots shows up.
main1.m
%---------------
filename='file1.mat'
load(filename)
figure(1)
plot(data.x,data.y) %data from structure of the mat file
while 1%so that it continues asking for a region
figure(1)
'choose a point or press e to exit'
[x1,y1,key]=ginput(1) %point1(x1,y1)
[data1y,data2y,datax]=function1(x1,y1) %function1 is an outside function that does
%the analysis of the points x1,y1 that were picked from the user
guide_fun1(data1y,data2y,datax)
if (key == 'e')
display('End')
break;
else
display('click point')
end
end
The function that I have created using GUIDE is shown below
guide_fun1.m
%-------------
function varargout = guide_fun1(varargin)
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', #guide_fun1_OpeningFcn, ...
'gui_OutputFcn', #guide_fun1_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before guide_fun1 is made visible.
function guide_fun1_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to guide_fun1 (see VARARGIN)
handles.data1y = varargin{1};
handles.data2y = varargin{2};
handles.datax = varargin{3};
% Choose default command line output for guide_fun1
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes guide_fun1 wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = guide_fun1_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes when selected object is changed in uipanel1.
function uipanel1_SelectionChangeFcn(hObject, eventdata, handles)
% hObject handle to the selected object in uipanel1
% eventdata structure with the following fields (see UIBUTTONGROUP)
% EventName: string 'SelectionChanged' (read only)
% OldValue: handle of the previously selected object or empty if none was selected
% NewValue: handle of the currently selected object
% handles structure with handles and user data (see GUIDATA)
switch get(eventdata.NewValue,'Tag') % Get Tag of selected object.
case 'radiobutton1'
% Code for when radiobutton1 is selected.
semilogy(handles.datax,handles.data1y,'-r','LineWidth',4);
axis([0 1 0. 1]);
case 'radiobutton2'
% Code for when radiobutton2 is selected.
semilogy(handles.datax,handles.data2y,'-g','LineWidth',4)
axis([0 1 0. 1]);
end
% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
% hObject handle to slider1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
xminval=0;%set min value for x axis
xmaxval=1;%set max value for x axis
xsld_step = [0.01 0.1];%slider step
axis([xminval xmaxval 0 1]);%set axis range for plot
set(hObject,'Min',xminval);
set(hObject,'Max',xmaxval);
set(hObject, 'SliderStep', xsld_step);
new_xmaxval=get(hObject,'Value')
%this is to avoid the error in case the user slides to zero
if new_xmaxval<0.01
'min value for x axis maximum range is 0.01'
new_xmaxval=0.01
end
axis([xminval new_xmaxval 0 1]);%set new axis range for plot
% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
% hObject handle to slider1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
I have 3 issues that I would like to fix.
When the slider shows up, the slider position is at zero but since my initial plot is from 0 to 1 , I would like the slider position to be at 1. Is there any way to set the slider initial position?
When I move the slider position to another value, let's say at 0.4 and then I press the next radio button ('button 2') then my graph is shown with values from 0 to 1 on the x axis but the slider position remains where it was,at the 0.4 point, so it does not look right. I would like when I press 'button 2' either to have both my slider go back to value 1 and my graph to show the plot from 0 to 1 or if my slider remains in the previous position (0.4) to have my graph show the plot from 0 to 0.4 so both the slider and the graph agree. I understand that to do that I have to figure out a way to connect the slider with the radio buttons but I do not know how to do that.
When I click on the first point (point1) and the GUIDE window opens up there is no graph and none of the buttons are pressed (which is what I want). Then I push the button I want and slide the slider to the x axis range that I want to examine. But when I click another point that I want to examine (point1) in the figure(1) plot then the GUIDE window remains as is with the last button clicked and the slider where it was from the previous point and only when I click on 'radio button1' or 'radio button2' it updates to the graph of the new point1. I would like when I click on a new point1 the GUIDE window to become like the first time it opens, no plot shown and no buttons pressed (basically to reset from the previous loop).
I would appreciate any help on this, my knowledge of MATLAB is limited so any guidance on this would be really helpful.
I was able to solve some of the issues with your comments, but unfortunately not all.
I solved this by adding this command set(handles.slider1,'value',1) in guide_fun1_OpeningFcn and the slider goes to 1 every time it restarts, so it works
I changed in uipanel1_SelectionChangeFcn
case 'radiobutton1'
% Code for when radiobutton1 is selected.
semilogy(handles.datax,handles.data1y,'-r','LineWidth',4);
axis([0 1 0.1]);
set(handles.slider1,'value',1);%NEW LINE
so that every time I click on this button the slider goes to value 1 since my axis goes from 0 to 1 but it does not work, there is no error, it just does not update the slider when i click the first button.
3 . I am not sure how to do that. I thought every time the GUI reopens it should automatically reinitialize. Can you give me an example of what an initialization subroutine looks like?

It would be VERY helpful if you showed screenshots of your GUI.
As a starting point for your 3 issues, I would try the following:
Initial slider position. Set the slider value in guide_fun1_OpeningFcn, right before guidata(hObject, handles);
Updating slider position with button press. Set the slider value in the radio buttons' call backs as well as in uipanel1_SelectionChangeFcn. Don't forget to put guidata(hObject, handles); at the end of each callback or method that modifies handles. Although, the set shouldn't change handles, just a property of a handle graphics object.
Make an initialization subroutine and run it from guide_fun1_OpeningFcn or, if you handles the clicks with the GUI instead of ginput, the axes click/selection callback.
A more general observation is that you should not have to put your GUI in a while loop using ginput to get input data. You could handle the axes clicks from the GUI code.

Related

How to make ginput confine to current axes for selecting a seed point

I am attaching a sample GUI codes, which has two axes with 2 images and when I use ginput to select seed point I am able to select on either axes, Is there anyway to limit the ginput to a specific axes
% --- Executes on button press in open.
function open_Callback(hObject, eventdata, handles)
% hObject handle to open (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global img1;
global img2;
img1 = imread('peppers.png');
img2 = imread('rice.png');
axes(handles.axes1);
imshow(img1,[]);
axes(handles.axes2);
imshow(img2,[]);
% --- Executes on button press in seedpointSelect.
function seedpointSelect_Callback(hObject, eventdata, handles)
% hObject handle to seedpointSelect (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global img1;
global img2;
global x;
global y;
axes(handles.axes1);
imshow(img1,[]);
[y,x] = ginput(handles.axes1);
y = round(y); x = round(x);
set(handles.xcord,'String',num2str(x));
set(handles.ycord,'String',num2str(y));
Any help on limiting ginput to a specific axes,
Thanks,
Gopi
In older versions of MATLAB you used to be able to change the HitTest property of the axes to ignore the click from ginput
set(handles.axes2, 'Hittest', 'off')
The better approach though is to use ButtonDownFcn as you have much more control over mouse events with an axes object.
From within your OpeningFcn
set(handles.axes1, 'ButtonDownFcn', #mouseCallback)
Then you'll need to create the callback function
function mouseCallback(src, evnt)
handles = guidata(src);
% Get the current point
xyz = get(src, 'CurrentPoint');
x = xyz(1,1);
y = xyz(1,2);
% Store x/y here or whatever you need to do
end
Don't use ginput, create a mouse click callback instead (ButtonDownFcn). You can set the callback to, for example, remove the callback function from the axis. In your main program, which sets the callback, you then waitfor that property to change. As soon as the user clicks, you get control back, and you can then read the location of the last mouse click (CurrentPoint). Note that the position you read out is in axis coordinates, not screen pixels. This is a good thing, it most likely corresponds to a pixel in the image displayed.

Using addlister in MATLAB GUI seems to "delete" existing handles

I am quite new to MATLAB GUI programming (using GUIDE sorry) and I have the following issue: The GUI displays on an axis an image sequence stored in a cell array. I have a couple of pushbuttons and a slider to scroll through the sequence. In order to get a 'continuous slider' I use a listener, which kind of works but creates some problems:
1) When I press the slider, a figure is created and the first frame of the sequence is displayed in it, but as I move the slider the sequence is displayed in the axis of my GUI (which is what I want) and the figure becomes empty. Can anybody tell me why this figure is created and how can I avoid it?
2) Once I press the slider button and thus use the listener, all handles inside the GUI are not functionnal as Matlab does not recognize them and I'm stuck with a functionnal slider/display but I can't use the pushbuttons.
Any ideas on why this happens? Here is the code I use in the Create Function of the slider:
function slider2_Frame_Video_Callback(hObject, eventdata, handles)
hListener = addlistener(hObject,'ContinuousValueChange',#(a,b) slider2_Frame_Video_Callback(hObject, eventdata, handles)); % a and b are dummy arguments
guidata(hObject,handles)
In the slider callback, the code looks like this (basically imshow in the current axis):
axes(hAxis)
imshow(Movie{frame},'parent',hAxis);
drawnow
% This does not work either as handles.edit_FrameNumber is not recognized by Matlab
set(handles.edit_FrameNumber, 'String', frame);
guidata(hObject,handles);
Any hints are welcome thanks!
I wonder if part of the problem is that a listener is being instantiated each time the user moves the slider since the listener code is within this callback AND that the callback being provided to the listener (seems like some kind of strange back-and-forth there). So every time the user releases the mouse button after a slide, a new listener is created. This may be causing some problems with the other buttons not being responsive.
Rather than instantiating the listener there, I would do this in the Opening_Fcn of your GUI:
% --- Executes just before frameSlider is made visible.
function frameSlider_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to frameSlider (see VARARGIN)
% Choose default command line output for frameSlider
handles.output = hObject;
if ~isfield(handles,'hListener')
handles.hListener = ...
addlistener(handles.slider1,'ContinuousValueChange',#respondToContSlideCallback);
end
% Update handles structure
guidata(hObject, handles);
My GUI is named frameSlider; yours will be something else. The above creates one listener with a callback to a function that you will need to define in the same *.m file, respondToContSlideCallback.
A sample body for the callback that is to respond to the continuous slide is
% --- Executes on slider movement.
function respondToContSlideCallback(hObject, eventdata)
% hObject handle to slider1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
% first we need the handles structure which we can get from hObject
handles = guidata(hObject);
% test to display the current value along the slider
disp(['at slider coordinate ' num2str(get(hObject,'Value'))]);
If you run this code, the Command Window will display continuously the slider coordinate as you move the slider from end to end.
Your above code has a Movies cell array. How is that being accessed by your callback? Is it a global variable or ..? Where does hist come from? If Movies is the result of some other function call, then it can be saved to handles too (in whichever location it gets loaded from file). I suppose you will also have to map the slider control coordinates to the number of frames that you have (though maybe you have already done this?).

Matlab GUIDE: how can I scatter when the user clicks?

I want to program the 'axes1' section of a new GUIDE project in a way that it scatters the points inside the axes when the user clicks on them.
I am new to GUIDE and I don't fully understand how hObjec, handles, etc. work. What I have gathered so far from other posts is the following piece of code:
% --- Executes on mouse press over axes background.
function axes1_ButtonDownFcn(hObject, eventdata, handles)
% hObject handle to axes1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%axesHandle = get(hObject,'Parent');
coordinates = get(hObject,'CurrentPoint');
coordinates = coordinates(1,1:2);
scatter(coordinates(1),coordinates(2));
I am not using the 'get(hObject,'Parent')' section because that was used in the case you use an image to display in the axes and that is not my case.
Can someone please explain how can I do this?
Thanks in advance for your time
I solved this months ago but I didn't post the solution!
It was easier than I thought, I just had to store each mouse press as a (x, y) point and then use plot:
% ND = Nodes in the network
ND = zeros(N,2);
ND(1,:) = ginput(1);
plot(ND(1,1),ND(1,2),'ko','MarkerSize',12);
hold on;
for i=2:N
ND(i,:) = ginput(1);
plot(ND(i,1),ND(i,2),'ko','MarkerSize',12);
end

Editing one function in GUIDE, changes all functions?

I am using Matlab's GUIDE for the first time, I am trying to edit one of the two push button functions (both open an image), but editing one changes all of them. Here is a bit of code:
% --- Executes on button press in Floating.
function Floating_Callback(hObject, eventdata, handles)
clc;
axes(handles.axes1);
[Float, PathName, FilterIndex] = uigetfile('*.bmp');
if(Float ~= 0)
Floating = fullfile(PathName, Float);
FloatArray = imread(Floating);
imshow(FloatArray);
axis on;
end
% Update handles structure
guidata(hObject, handles);
% hObject handle to Floating (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% --- Executes on button press in Reference.
function Reference_Callback(hObject, eventdata, handles)
clc;
axes(handles.axes2);
[Ref, PathName, FilterIndex] = uigetfile('*.bmp');
if(Ref ~= 0)
Reference = fullfile(PathName, Ref);
ReferenceArray = imread(Reference);
image(ReferenceArray);
end
% Update handles structure
guidata(hObject, handles);
For example,
image(ReferenceArray)
will open an image in RBG, but
imshow(FloatArray)
will open in grayscale (I also do not understand why that is). But my main concern is after opening up
imshow(FloatArray)
the other image will automatically turn grayscale. I am very confused... Also, as far as I know the images ARE already grayscale, at least they are when I open them in MS paint or ImageJ.
It would be better to explicitly specify the parent handle whenever you are doing GUI stuff. For example:
imshow(img, 'Parent',handles.ax1)
and
axis(handles.ax1, 'on')
As for images and colormaps, you should understand the type of images MATLAB supports (indexed vs. truecolor). Also note that a figure has only one colormap applied to all images, although there are techniques to overcome this.

Using a radio button panel to choose different graphing options

I am trying to create a GUI that will take several inputs and run them through several functions. I wish to use a radio button panel to switch between different graphs, but i just cant seem to get it working. Here is a sample of my code.
switch get(eventdata.NewValue,'Tag') % Get Tag of selected object
case 'button1'
status1 = str2double(get(handles.button1,'Value'));
if status1 == 1;
axes(handles.axes1)
grid on;
plot(x1,y1)
end
case 'button2'
status2 = str2double(get(handles.button2,'Value'));
if status2 == 1;
axes(handles.axes1)
grid on;
plot(x2,y2)
end
case 'button3'
status3 = str2double(get(handles.button3,'Value'));
if status3 ==1
plot(x3,y3)
end
otherwise
% Code for when there is no match.
end
It appears that you are trying to create a radio button panel in a way similar to this example tutorial on blinkdagger.com. Specifically, I believe you are trying to create a SelectionChangeFcn to define how the radio buttons modify your GUI. I would suggest the following:
First, instead of replotting a line every time a radio button is selected, I would suggest that you plot all of your lines when you create your GUI and then adjust the 'Visible' property of the lines to either 'on' or 'off' depending on which button is selected. When you make your GUI, you can add these lines somewhere in your code (after the axes is created and placed in the handles variable):
handles = guidata(hObject); % Retrieve handles structure for GUI
set(handles.axes1,'NextPlot','add'); % Set axes to allow multiple plots
lineHandles = [plot(handles.axes1,x1,y1,'Visible','off') ...
plot(handles.axes1,x2,y2,'Visible','off') ...
plot(handles.axes1,x3,y3,'Visible','off')];
handles.lineHandles = lineHandles; % Update handles structure
guidata(hObject,handles); % Save handles structure
This will plot three sets of lines on the same axes. These lines are initially not visible, and handles to each plotted line are collected in a vector variable lineHandles. The last two lines above add the line handles to the handles structure and update the GUI data (hObject should be a handle to the GUI figure window!).
Now, you can use the following for your SelectionChangeFcn:
handles = guidata(hObject); % Retrieve handles structure for GUI
buttonTags = {'button1' 'button2' 'button3'};
if ~isempty(eventdata.OldValue), % Check for an old selected object
oldTag = get(eventdata.OldValue,'Tag'), % Get Tag of old selected object
index = strcmp(oldTag,buttonTags); % Find index of match in buttonTags
set(handles.lineHandles(index),'Visible','off'); % Turn old line off
end
newTag = get(eventdata.NewValue,'Tag'), % Get Tag of new selected object
index = strcmp(newTag,buttonTags); % Find index of match in buttonTags
set(handles.lineHandles(index),'Visible','on'); % Turn new line on
guidata(hObject,handles); % Save handles structure
NOTE: If you ever want to change any of the three lines that are plotted, you can simply set the 'XData' and 'YData' properties of one of the line handles. As an example, this updates the first plotted line with new x and y data:
set(handles.lineHandles(1),'XData',xNew,'YData',yNew);
Unless you have a good reason to do otherwise, I think you should put the plotting code inside the callback for each radio button.
No need to do this big switchyard.
% --- Executes on button press in radiobutton1.
function radiobutton1_Callback(hObject, eventdata, handles)
% hObject handle to radiobutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of radiobutton1
%%
%get the values of x y into this callback as you see fit
plot(x,y)
Also, the 'value' that comes out of the button it is already a double for radio buttons. No need to convert it as you are doing.