Graphing with GUI - matlab

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'

Related

How to pass the value of a table to a matrix

Im trying to do a GUI in matlab that accepts the values in a table to converting it to a matrix, but the idea is that a user can set the number of rows and columns first.
The panel looks like this
and the code for the push button is
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)
rows =str2double(get(handles.edit_rows,'String'));
cols=str2double(get(handles.edit_cols,'String'));
num_elem=cell(rows,cols);
num_elem(:,:)={"};
set(handles.uitable1,'Data',num_elem)
set(handles.uitable1,'ColumnEditable',true(1,cols))
But then, how can export or convert to a matrix so I can apply functions to it?
UPDATE
With the help of byetisener I updated the code to
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)
filas=str2double(get(handles.edit_fila,'String'));
column=str2double(get(handles.edit_col,'String'));
num_elem=cell(filas,column);
num_elem(:,:)={''};
set(handles.uitable1,'Data',num_elem)
set(handles.uitable1,'ColumnEditable',true(1,column))
handles.uitable1.Data = cell(filas, column);
matrix = cell2mat(handles.uitable1.Data);
matrix
but this is giving an empty matrix
It is not taking the values of the cells, it is supposed that the button resizes and copy the values at the same time, if not how con copy in another button once the matrix is resized?
There are some problems about your code:
You do not really assign values here, you are just setting the Data of the uitable to an array of empty cells.
num_elem =
1×2 cell array
{0×0 char} {0×0 char}
If you ever succeed, you code will write everything you want to only the first column of the uitable. Because you are not iterating through rows. The pushbutton only adds to the first row.
cell2mat() function won't work if you have different data types in your table. You may think that you do not have different data types, but empty cells are type cell and the data you enter is type double, so there it is.
To solve all of this I have rewritten a callback function for you. You may directly paste this code to your callback, replacing yours. I should give you the matrix you want at the end, it does in my computer.
filas = str2double(handles.edit_fila.String);
column = str2double(handles.edit_col.String);
% This loop looks for an empty row to write new data
for i = 1:length(handles.uitable1.Data)
if isempty(handles.uitable1.Data{i,1})
handles.uitable1.Data(i,1) = {filas};
handles.uitable1.Data(i,2) = {column};
break;
else
disp('Error occured');
end
end
% This double for loop check if there are any empty cells
% if it finds one, it changes it to 0, so all the cells have the same type
for i = 1:length(handles.uitable1.Data)
for j = 1:2
if isempty(handles.uitable1.Data{i,j})
handles.uitable1.Data(i,j) = {0};
else
disp('Error occured');
end
end
end
matrix = cell2mat(handles.uitable1.Data); % The matrix you want
Just check if all the variable names are the same and do not forget to accept is as an answer. Hope it helps.
I am not sure if this answers you question but you can follow this approach.
First of all, if you are interested, using dot notation is faster in MATLAB than setter and getter methods.
So, what you can do is:
handles.uitable1.Data = cell(rows, cols);
or, of course, alternatively:
set(handles.uitable1, 'Data', cell(rows,cols));
If what you want to is to convert the data in uitable to a matrix, you can use:
matrix = cell2mat(handles.uitable1.Data);
If you table contains non-numeric values:
tableData = handles.uitable1.Data;
tableData = [str2double(tableData(:, 1)), cell2mat(tableData(:, 2))];
Hope this helps. Let me know if you solve your problem.

Determine whether parsed varargin input should be passed as an argument vs. parsing within each function

I have a set of functions that takes a cell array of tables and plots data from each table as a subplot on a figure. I have been learning to use the inputParser class to handle varargin inputs, and have that here. The optional parameters are for choosing plot type (plot or bar) and for choosing the names of the variables to plot from the input tables.
In my scenario, the inputs need to be passed along about 3 functions deep, so I'm wondering about best practices for doing this. In my current setup, the outermost function (main) takes a varargin input and parses the inputs by assigning defaults and such. Then I'm wondering, when it comes time to pass these inputs to the next function, is it best to pass the parsedInputs data Results struct down the line, or is it better to have the next function also take a varargin argument and to repeat the parsing process again? I'm not sure what the best way to go about this is. My code is below. The main script for test purposes looks as follows:
% RUN TEST CASE
Tables{1} = table([1 2 3]' , [6 7 8]', 'VariableNames', {'diam', 'length'});
Tables{2} = table([1 2 6]' , [6 9 2]', 'VariableNames', {'diam', 'length'});
Tables{3} = table([3 9 11]', [7 4 1]', 'VariableNames', {'diam', 'length'});
main(Tables);
The main function takes a (required) cell array of tables (Tables) and variable argument parameters, such as 'xVariable', 'yVariable', 'plotType'.
function main(Tables, varargin)%PlotParams, DICTS)
% parse inputs
parsedInputs = parse_plot_inputs(Tables, varargin);
% create figure of subplots
figure;
make_subplots_from_tables(parsedInputs);
end
A parse_plot_inputs function takes care of the default value assignment, etc.:
function parsedInputs = parse_plot_inputs(Tables, vararginList)
% input parser function for this specific plotting case
p = inputParser;
addRequired(p, 'Tables', #iscell);
addParameter(p, 'xVariable', 'diam');
addParameter(p, 'yVariable', 'length');
addParameter(p, 'plotType', 'plot');
parse(p, Tables, vararginList{:});
parsedInputs = p;
end
make_subplots_from_tables then loops through the cell array of tables, and calls plot_special to plot each of them on its own subplot.
function make_subplots_from_tables(parsedInputs)
% unpack parsed inputs
Tables = parsedInputs.Results.Tables;
% plot each table as a subplot
numTables = length(Tables);
for i = 1:numTables
subplot(numTables, 1, i); hold on;
plot_special(Tables{i}, parsedInputs)
end
end
plot_special is the "base" function in this scenario that calls the MATLAB plot functions:
function plot_special(T, parsedInputs)
% unpack parsed inputs
xVariable = parsedInputs.Results.xVariable;
yVariable = parsedInputs.Results.yVariable;
plotType = parsedInputs.Results.plotType;
% plot single table on one plot
xVals = T.(xVariable);
yVals = T.(yVariable);
switch plotType
case 'plot'
plot(xVals, yVals, '-x');
case 'bar'
bar(xVals, yVals);
otherwise
error('invalid plot type');
end
end
I am unsure whether this is the best method for taking in arguments and for using them in subsequent functions. This method works, although I'm not sure that it's the best practice, nor the most flexible, for example, considering the scenario when I would like to use plot_special on its own, and would like to be able to pass it arguments for xVariable, yVariable, etc. if need be. Given that it is currently dependent on the parsedInputs list from the main function, that wouldn't be doable. However, I'm unsure what another way to define it would be. I considered having an if statement built in along with a varargin input argument that checks whether the varargin is an already-parsed struct, or if it's getting the variables directly and needs to call the parse_plot_inputs itself to get things working. Any advice would be great.
There is no single "best" method, it all depends on circumstances. What you are doing is fine if the functions that take an inputParser object are private sub-functions. If they are generic functions that should work independently, they should have their own argument parsing. One thing you could do, given that you want plot_special to be a stand-alone function, is as follows:
function main(Tables, varargin)
figure;
make_subplots_from_tables(Tables, varargin{:});
end
function make_subplots_from_tables(Tables, varargin)
% plot each table as a subplot
numTables = length(Tables);
for i = 1:numTables
subplot(numTables, 1, i); hold on;
plot_special(Tables{i}, varargin{:})
end
end
function plot_special(T, varargin)
% parse `varargin` to yield `xVariable`, `yVariable`, `plotType`
% plot single table on one plot
end
This way you do the parameter parsing only where necessary, although it is done once for each table plotted, rather than only once for the whole graph. This is probably a very minor issue though, since parameter parsing is not nearly as expensive as plotting.

Plotting in an axes from a function

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);

can't apply image gaussian blur filter using slider in matlab

I am working in image processing task using matlab,I have made a slider inside a dialog to apply and update gaussian blur filter on an image which is shown in axes
but it can not apply it,it shows that error
Error in ==> MatlabTestProject>name at 392
axes(handles.axes4);
??? Error while evaluating uicontrol Callback
this is my code
function mygui()
out = dialog('WindowStyle', 'normal', 'Name', 'My Dialog','Resize','off');
hSlider = uicontrol('Style','slider','Min',3,'Max',15,'Value',3,'Callback',#gaussian_blur);
%hListener = addlistener(hSlider,'Value','PostSet',#(s,e) disp('hi'));
function gaussian_blur(s,e,handles)
global imag;
slider_value = get(s,'Value');
slider_value=round(slider_value);
%display(slider_value);
%disp('hello')
%create filter
%sliderValueTxt=num2str(slider_value);
%set(handles.kSizeValueText ,'String',sliderValueTxt);
h = fspecial('gaussian', slider_value,0.5);
imag=imfilter(imag,h,'conv');
axes(handles.axes4);
imshow(imag)
% --------------------------------------------------------------------
function gaussianBlur_Callback(hObject, eventdata, handles)
% hObject handle to gaussianBlur (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
gaussian_dialog_Gui();
You're actually really close! All you need to do is include handles as an argument to the function gaussian_blur when defining the slider's listener object callback.
i.e replace this line: (it looks like a test line though)
hListener = addlistener(hSlider,'Value','PostSet',#(s,e) disp('hi'));
with something like this:
hListener = addlistener(hslider,'Value','PostSet',#(s,e) gaussian_blur(handles));
Just to be sure it works I created a test GUI programmatically using an axes and a slider and it works very well! Actually I changed a bit the filter to see an effect on my test image, but it should work as well in your case:
function GaussianSlider()
clear
clc
close all
handles.Image = imread('peppers.png');
handles.fig = figure('Position',[500 500 600 600],'Units','pixels');
handles.axes1 = axes('Units','pixels','Position',[50 100 400 400]);
handles.slider = uicontrol('Style','slider','Position',[50 50 400 20],'Min',3,'Max',15,'Value',3);%// I commented this for the purpose of demonstration. 'Callback',#gaussian_blur(handles));
%// That's the important part: add 'handles' as input argument to
%// gaussian_blur.
handles.Listener = addlistener(handles.slider,'Value','PostSet',#(s,e) gaussian_blur(handles));
imshow(handles.Image,'Parent',handles.axes1);
guidata(handles.fig);
function gaussian_blur(handles)
slider_value = round(get(handles.slider,'Value'));
%// I modified a bit the filter to see the effect
h = fspecial('gaussian',slider_value,slider_value);
handles.Image=imfilter(handles.Image,h,'conv');
axes(handles.axes1);
imshow(handles.Image)
end
end
If we look at 2 screenshots (i.e. 2 different slider positions):
and after moving the slider:
That's it! Hope that helps! If something is unclear please tell me.
Oh and in case you do not know: The actual callback of a slider is only executed when you release the button or press either arrow. As long as you hold the slider and move it, it's only the listener's callback that will be executed.

How to read multiple lines by individual in an edit text with a value of Max=5 in Matlab?

I have in my gui an edit text field that accepts multiple lines with a Max value of 5, and i can't find a way to display a matrix with the input values...something like this:
m=[m(1) m(2) m(3) m(4) m(5)];
set(handles.show,'string',m)
how can i store the values in the calculate callback..every time i run this, it brings me an error..
function masa_Callback(hObject, eventdata, handles)
% hObject handle to masa (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%h_edit is the handle to the edit box
m=str2double(get(hObject,'String'));
function calculate_Callback(hObject, eventdata, handles)
% hObject handle to agregarm (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
f = str2double(get(h_fuerza,'string')); %h_edit is the handle to the edit box
m = str2double(get(h_masa,'string')); %h_edit is the handle to the edit box
[row, column] = size(m);
for i = 1:row
eval(m{i,:}) %evaluate each line as in MATLAB command prompt
end
I have the masa_callback,rigidez_callback and fuerza_callback i try to read the user input in the edit text box...so i want to pass those values to the calculate_callback as an array to perform certain operations according to the value of n...the error that i am getting is that when for example n=2, i add two values in the masa_callback column and fuerza_callback and 3 values in the rigidez_callback, those values are passed to the case n==2, and when my program tries to display for example the matrix m, it displays all the values i enter together in the spaces of m(1) and m(2)...i want to put only each separated value, not joined together!...How can i fix this,, i believe that is whith an array and a loop but i dont know how, and how to pass the array values to the equation to perform operations(as numbers) and display it as string
To fix the problem with the input (assuming you have your data in some cell array, and that handles.show refers to a text box), use strvcat:
someCellArray = {'a','b'};
m = strvcat(someCellArray{:});
set(handles.show,'string',m)
Your problem stems from the line
m = str2double(get(h_masa,'string'));
You do not want to convert the string to double.
Since the String property actually returns a multiline string, you have to modify your code like this:
m = get(h_masa,'String');
nRows = size(m,1);
for iRow = 1:nRows
eval(m(i,:));
end