Plotting in an axes from a function - matlab

I am working on a GUI in MATLAB; I used the GUIDE in the command window.
I have several pushbuttons.
Now the problem, I have a function, in a pusbhbutton4 and when I click on it I want to plot the result in three specific axes (10 - 12).
But does not work.
The code:
function pointsQRS = MyCustomPushButtonFunctionQRS10(VxQRS, VyQRS, VzQRS)
VxQRS=[[0:length(VxQRS)-1]' VxQRS];
axes(handles.axes10);
plot(VxQRS(:,2));
grid on
Vx_QRS=ginput;
x_pointsQRS=VxQRS(Vx_QRS(1,1)<=VxQRS(:,1) & Vx_QRS(2,1)>=VxQRS(:,1),:);
m=1;
VyQRS=[[0:length(VyQRS)-1]' VyQRS];
axes(handles.axes11);
plot(VyQRS(:,2));
grid on
Vy_QRS=ginput;
y_pointsQRS=VyQRS(Vy_QRS(1,1)<=VyQRS(:,1) & Vy_QRS(2,1)>=VyQRS(:,1),:);
if size(y_pointsQRS,1)<m
m=2;
end
VzQRS=[[0:length(VzQRS)-1]' VzQRS];
axes(handles.axes12);
plot(VzQRS(:,2));
grid on
Vz_QRS=ginput;
z_pointsQRS=VzQRS(Vz_QRS(1,1)<=VzQRS(:,1) & Vz_QRS(2,1)>=VzQRS(:,1),:);
if size(z_pointsQRS,1)<m
m=3;
end
switch m
case 1
x_pointQRS=x_pointsQRS;
y_pointQRS=y_pointsQRS(x_pointsQRS(1,1)<=y_pointsQRS(:,1) & x_pointsQRS(end,1)>=y_pointsQRS(:,1),:);
z_pointQRS=z_pointsQRS(x_pointsQRS(1,1)<=z_pointsQRS(:,1) & x_pointsQRS(end,1)>=z_pointsQRS(:,1),:);
case 2
y_pointQRS=y_pointsQRS;
x_pointQRS=x_pointsQRS(y_pointsQRS(1,1)<=x_pointsQRS(:,1) & y_pointsQRS(end,1)>=x_pointsQRS(:,1),:);
z_pointQRS=x_pointsQRS(y_pointsQRS(1,1)<=z_pointsQRS(:,1) & y_pointsQRS(end,1)>=z_pointsQRS(:,1),:);
case 3
z_pointQRS=z_pointsQRS;
x_pointQRS=x_pointsQRS(z_pointsQRS(1,1)<=x_pointsQRS(:,1) & z_pointsQRS(end,1)>=x_pointsQRS(:,1),:);
y_pointQRS=y_pointsQRS(z_pointsQRS(1,1)<=y_pointsQRS(:,1) & z_pointsQRS(end,1)>=y_pointsQRS(:,1),:);
end
size_min=min([size(x_pointQRS,1) size(y_pointQRS,1) size(z_pointQRS,1)])
pointsQRS([1:size_min],:)=[x_pointQRS([1:size_min],2) y_pointQRS([1:size_min],2) z_pointQRS([1:size_min],2)];
if size_min==0
error('Wrong.');
end
end
The pushbutton code:
% --- Executes on button press in pushbutton4.
function pushbutton4_Callback(hObject, eventdata, Data)
% hObject handle to pushbutton4 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
pointsQRS = MyCustomPushButtonFunctionQRS10(Data.fileData(:,1), Data.fileData(:,2), Data.fileData(:,3))
save 'pointsQRS.mat' -mat pointsQRS
Error I'm still getting:
Undefined variable "handles" or class "handles.axes10".
Error in MyCustomPushButtonFunctionQRS10 (line 3)
axes(handles.axes10);
Error in VKG_Zobrazovac>pushbutton4_Callback (line 156)
pointsQRS = MyCustomPushButtonFunctionQRS10(Data.fileData(:,1), Data.fileData(:,2), Data.fileData(:,3))
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in VKG_Zobrazovac (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in #(hObject,eventdata)VKG_Zobrazovac('pushbutton4_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback
Could you please give me any hint how to make it work properly?

You are not passing the handles struct to MyCustomPushButtonFunctionQRS10 (or as you call it, Data) so it has no way to access the axes handles stored in handles. You should pass handles as an input argument.
pointsQRS = MyCustomPushButtonFunctionQRS10(Data.fileData(:,1), ...
Data.fileData(:,2), ...
Data.fileData(:,3), ...
Data)
And then your callback would accept a fourth input
function pointsQRS = MyCustomPushButtonFunctionQRS10(VxQRS, VyQRS, VzQRS, handles)
Additionally, I would recommend using the 'Parent' property of plot to specify the parent axes rather than using axes.
plot(VxQRS(:,2), 'Parent', handles.axes10);
grid(handles.axes10, 'on')
Vx_QRS = ginput(handles.axes10);

Related

Loading multiple images in Matlab GUI

I want to load multiple images in Matlab GUI.
Algorithm below:
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[filename path] = uigetfile('*.jpg','*.png','Chose files to
load','MultiSelect','on');
if isequal(filename,0) || isequal(path,0)
return
end
if iscell(filename)
img = cell(size(filename));
for ii = 1:numel(filename)
img{ii} = imread(fullfile(path,filename{ii}));
end
else
img{1} = imread(fullfile(path,filename));
end
filename = strcat(path,filename);
fullpathname = strcat(path, filename);
set(handles.edit1,'String', fullpathname);
fileID = fopen(strcat(path, filename), 'r');
It works in case of loading one image, but in case of loading multiple images, it gives mi subsequent error:
Error using imread>parse_inputs (line 457)
The file name or URL argument must be a string.
Error in imread (line 316)
[filename, fmt_s, extraArgs] = parse_inputs(varargin{:});
Error in untitled>pushbutton1_Callback (line 112)
im = rgb2gray(imread(filename));
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in untitled (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in
#(hObject,eventdata)
untitled('pushbutton1_Callback',hObject,eventdata,guidata(hObject))
Could you please give me a hint, so I could make it functional?
uigetfile returns in filename:
a character vector or a cell array of character vectors.
(From the documentation). The former happens when selecting one file, the latter when selecting multiple files.
Thus, if you want to be ale to select multiple files, your code needs to handle that case by checking to see if iscell(filename), and if so, looping over each of its elements.
Also, please use fullfile to concatenate parts of a path or file name, it will prevent portability issues down the road.
You could write code like this:
[filename,path] = uigetfile({'*.jpg';'*.png'},'Chose files to load','MultiSelect','on');
if isequal(filename,0)
return
end
if iscell(filename)
img = cell(size(filename));
for ii = 1:numel(filename)
img{ii} = imread(fullfile(path,filename{ii}));
end
else
img{1} = imread(fullfile(path,filename));
end
Now img is a cell array containing all the images selected.

unable to store variable in Matlab Gui

I know several variants of this issue have been discussed elsewhere, but I am still unable to solve the problem. Please help.
I have created a function as part of a larger gui, but I am unable to store three data variables (AveX, AveY, AveZ) for later use by guidata(hObject, handles).
What am I doing wrong?
Here is the function:
%call all checkbox values
for i = 1:30
checkboxes=get(handles.(sprintf('checkboxAv%d',i)),'value')
Checkboxes(i,1)=checkboxes(1,1);
end
plotdata=handles.plotdata;
[row,col] = find(Checkboxes==1)
num=length(plotdata{1,1}(:,1));
DataY = zeros(num,length(row));%zero matrix
%Average y data
for k=1:length(row)
DataY(:,k)=plotdata{row(k,1),col(k,1)}(:,4);
end
[m,n] = size(DataY)
if (n==1)
AveY=DataY'
elseif (n>1)
AveY=mean(DataY');
end
AveY=AveY';
%Average X data
for kk=1:length(row)
DataX(:,kk)=plotdata{row(kk,1),col(kk,1)}(:,1);
end
test=DataX(:,1);
comp=any(bsxfun(#minus,DataX,test),1)
S = sum(comp)
if (S > 0)
h=msgbox(['Note! Wavelength index for the selected samples are not identical.'])
end
[c,r] = size(DataY)
if (r==1)
AveX=DataX'
elseif (r>1)
AveX=mean(DataX');
end
AveX=AveX';
%Average Z data
for kkk=1:length(row)
DataZ(:,kkk)=plotdata{row(kkk,1),col(kkk,1)}(:,5);
end
[m,n] = size(DataZ)
if (n==1)
AveZ=DataZ'
elseif (n>1)
AveZ=mean(DataZ');
end
AveZ=AveZ';
handles.Aveheader=Aveheader
handles.AveX=AveX;
handles.AveY=AveY;
handles.AveZ=AveZ;
guidata(hObject, handles);
And here is the error message:
Undefined function or variable 'hObject'.
Error in CDanalyzer>AveragePlotFcn (line 5276)
guidata(hObject, handles);
Error in CDanalyzer>checkboxAv1_Callback (line 5076)
AveragePlotFcn(handles)
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in CDanalyzer (line 17)
gui_mainfcn(gui_State, varargin{:});
Error in
matlab.graphics.internal.figfile.FigFile/read>#(hObject,eventdata)CDanalyzer('checkboxAv1_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback
"guidata(object_handle,data) stores the variable data with the object specified by object_handle" you need to specify the object_handle. Currently hObject is undefined in this local function.
Use gcbo instead, which "returns the handle of the graphics object whose callback is executing":
guidata(hObject, handles);
becomes
guidata(gcbo, handles);
Alternatively, add hObject as an input to the function AveragePlotFcn. So:
function AveragePlotFcn(hObject,~)
...
end

Graphing with GUI

Using
x=-10:0.1:10
f=x+2
in basic m-file works fine.
But now I am trying to draw a plot using GUI, and by inputing a function.
It gives me bunch of errors. Could anyone explain how I can give values to the y when I have the range of x set?
% --- Executes on button press in zimet.
function zimet_Callback(hObject, eventdata, handles)
% hObject handle to zimet (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
x=-10:0.1:10;
f=inline(get(handles.vdj,'string'))
y(x)=f
axes(handles.axes)
plot(x,y)
color=get(handles.listbox, 'value')
switch color
case 2
set(plot(x,y),'color', 'r')
case 3
set(plot(x,y),'color', 'g')
case 4
set(plot(x,y),'color', 'b')
end
style=get(handles.popupmenu, 'value')
switch style
case 2
set(plot(x,y), 'linestyle','--')
case 3
set(plot(x,y), 'linestyle','-.')
case 4
set(plot(x,y), 'linestyle',':')
end
rezgis=get(handles.grid, 'value')
switch rezgis
case 1
grid on
case 2
grid off
end
Notice that according to the inline function documentation this function will be removed in future release; you can use, instead, anonymous functions (see below).
The inline function require, as input a string of characters while the get function returns the text of the edit box as a cellarray, therefore you have to convert it using the char function.
Also, once you have generated the inline object, it is you function, so you have to use it directly.
Using inline
You have to change your code this way:
x=-10:0.1:10;
% f=inline(get(handles.vdj,'string'))
% y(x)=f
f=inline(char(get(handles.vdj,'string')))
y=f(x)
axes(handles.axes)
ph=plot(x,y)
Using an anonymous function
You can achieve the same result by using anonymous functions this way:
x=-10:0.1:10;
% Get the function as string
f_str=char(get(handles.vdj,'string'))
% add #(x) to the string you've got
f_str=['#(x) ' f_str ];
% Create the anonymous function
fh = str2func(f_str)
% Evaluate the anonymous function
y=fh(x)
axes(handles.axes)
ph=plot(x,y)
Edit
You can fix the problem with the setting of the line color and style this way:
modify the call to plot by adding the return value (it is the handle to the plot (see above: ph=plot(x,y))
chance the calls to set by replacing the call to plot with the handle of the plot itself (the ph variable as above)
So, to change the color and the line style, in your switch section:
set(ph,'color','r')
set(ph,'linestyle','--')
Hope this helps,
Qapla'

MATLAB GUIDE button must be pressed twice?

I'm making a GUI with guide. I have a push button the user clicks and the callback is as folows : (what matters are the tirst two lines really...
function SetParticleRoiSize_Callback(hObject, eventdata, handles)
% hObject handle to SetParticleRoiSize (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles=guidata(hObject);
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
roiPoints=getPosition(particleroiSize); %-get tha parameters fo the rectanlge
partX1 = round(roiPoints(1));
partY1 = round(roiPoints(2));
partX2 = round(partX1 + roiPoints(3));
partY2 = round(partY1 + roiPoints(4)); % these are the ROi positions in pixels
roiHeight = round(roiPoints(3)); % - these are just the ROI width and height
roiWidth = round(roiPoints(4));
handles=guidata(hObject); %_ update all the handles...
handles.partX1=partX1;
handles.partX2=partX2;
handles.partY1=partY1;
handles.partY2=partY2;
handles.roicenterX = (partX1 + round(roiPoints(3))/2);
handles.roicenterY= (partY1 + round(roiPoints(4))/2);
handles.roiHeight = roiHeight;
handles.roiWidth = roiWidth;
current_slice = round(get(handles.Image_Slider,'Value'));
handles.current_slice=current_slice;
particleImage=handles.Image_Sequence_Data(partY1:partY2,partX1:partX2,current_slice);
handles.particleImage=particleImage;
set(handles.RoiSizeDisplay,'String',['Particle ROI is ',' ',num2str(roiHeight),' ', ' by ',num2str(roiWidth)] );
guidata(hObject,handles); %- at this point we now have the particle in the roi and the size of the roi stored.
The issue I am having is that when the user clicks the button the first time, nothing happens (i.e. the imrect line seems to not get called at all). When the user clicks the button again then they can draw a rectangle on the image but my program throws out an error
Error in imrect (line 83)
[h_group,draw_api] = imrectAPI(varargin{:});
Error in SemiAutomated_Fionv2p2_5>SetParticleRoiSize_Callback (line 291)
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
Error in gui_mainfcn (line 96)
feval(varargin{:});
Error in SemiAutomated_Fionv2p2_5 (line 56)
gui_mainfcn(gui_State, varargin{:});
Error in
#(hObject,eventdata)SemiAutomated_Fionv2p2_5('SetParticleRoiSize_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating uicontrol Callback
I guess the error is because there is no imrect created on the first button click.
Can someone please explain to me why this button needs to be clicked twice to work? (and even then it still gives an error...)
thanks...
-j
It looks like this call:
handles=guidata(hObject); %_ update all the handles...
is incorrectly used; you might need to replace it with guidata(hObject,handles) in order to actually update the handles structure. Moreover, since you already call guidata(hObject,handles) at the end of the callback you can delete this line altogether I think.
As it's currently implemented, you:
1) get the handles structure with handles = guidata(hObject);
2) store information in it
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
roiPoints=getPosition(particleroiSize); %-get tha parameters fo the rectanlge
partX1 = round(roiPoints(1));
partY1 = round(roiPoints(2));
partX2 = round(partX1 + roiPoints(3));
partY2 = round(partY1 + roiPoints(4)); % these are the ROi positions in pixels
roiHeight = round(roiPoints(3)); % - these are just the ROI width and height
roiWidth = round(roiPoints(4));
3) then call it again (handles = guidata(hObject))`.
Hence on your second call to retrieve the data you have not previously updated it, so I guess Matlab does not like it.
It might not be the specific cause of your error but I think it's worth checking.
I had 3 different axes in my figure. The first version of the program only had 1 axes so it worked fine. After adding the other axes to the GUI (via GUIDE) when I ran just imrect.. I think it was not choosing the axes I wanted..I added a parent handles.correct axes and now it works perfectly!

GUI uiwait/uiresume fig Matlab

I have a Matlab GUI which takes input in p array from different functions by different methods, my question is how I can terminates uiwait when the input of p array is taken, such that when any function of input is terminated successfully. I'm trying to put uiresume but it doesn't work on my side.
My code (Main Function):
function varargout = GUI(varargin)
if nargin == 0
fig = openfig(mfilename,'reuse');
handles = guihandles(fig);
guidata(fig, handles);
uiwait (fig);
if nargout > 0
varargout{1} = fig;
end
elseif ischar(varargin{1})
try
if (nargout)
[varargout{1:nargout}] = feval(varargin{:});
else
feval(varargin{:});
end
catch
end
end
I don't really get what exactly your code is supposed to do.
In any case:
uiresume has to be placed somewhere in a callback of the gui you're opening, since you're above code stops running in the uiwaitline.
So, you might have an "Ok"-Button on your GUI with a callback à la:
function ok_button_callback(object, evt, handles)
fig = ancestor(object, 'figure');
uiresume(fig);
end