Loading a certain column from an ascii file to a list box in gui matlab

Hello,
I am trying to load the content of a certain column in an ascii file where the column number is given by an edit box like that:
[filename pathname] = uigetfile({'*.dat;*.txt','ASCII Files';'*.*','All Files' },'Look for MELT data','MultiSelect','on');
fullpathname=strcat(pathname , filename);
x = fileread(fullpathname);
tScan = textscan(x, '%s %f %s','headerlines',1);
newScan = tScan{:};
col=getappdata(0,'edit16');% to read the entered column in the edit box
G=newScan(:,col);
set(handles.edit18,'string',G);
The problem is: if I entered the column number (col) as 1 it gives the correct content. But if entered any other number for (col) I get the following error
Index exceeds matrix dimensions.
Error in gui3>pushbutton8_Callback (line 406)
G=newScan(:,col);
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in gui3 (line 46)
gui_mainfcn(gui_State, varargin{:});
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)gui3('pushbutton8_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback
Could someone help me?

 Accepted Answer

It is a bad idea to store variables globally:
col=getappdata(0,'edit16')
If you open several instances of the GUI, they overwrite the application data of the root object. This suffers from the same horror as using global. I guess, that this is much easier and safer:
col = get(handles.edit16, 'String')
We cannot know, where the value of getappdata(0,'edit16') has been set to which value. Even for you it is not trivial to find out, where and when this value was set. But you can use at least the debugger to find the value:
dbstop if error
Now Matlab stops, when an error occurs and you can check the value of col.

8 Comments

It is not global. I defined col under the edit text call back as:
col=str2double(get(handles.edit16, 'string'))
setappdata(0,'edit16',col)
then i recalled it as:
col=getappdata(0,'edit16');
G=newScan(:,col);
set(handles.edit18,'string',G);
it works fine in case I entered 1 in the col edit box but for any other vlaues it shows the error message.
Storing a variable in the root's ApplicationData is "global", because you store the data in one cenrtal element and different instances of the GUI will overwrite the otehr values. Therefore these methods are equivalent and suffer from the same drawbacks:
global v
set(0, 'UserData', v) % same for: groot
setappdata(0, 'name', v) % same for: groot
There is no reason to use the indirection over the root object. Use the application data of the GUI, the handles struct or simply stay at using the contents of the edit field directly:
col = str2double(get(handles.edit16, 'string'));
If col=2 causes an error message in:
G=newScan(:,col);
the variable newScan does not have 2 columns. The line:
newScan = tScan{:}
is not clear: If tScan contains more than 1 element, a comma-separated list is replied, but this cannot be assigned to one variable. What do you get, if you run this manually:
tScan = textscan(aMatchingFileName, '%s %f %s','headerlines',1);
newScan = tScan{:}
1- By using
col = str2double(get(handles.edit16, 'string'));
only without setappdata and getappdata, the printed value on
set(handles.edit18,'string',col);
is simply the number I entered in the edit box. I need to load the content of the column associated with the column number entered in the edit box.
.....................................................
2- When I run from the command window
tScan = textscan(x, '%s %f %s','headerlines',1);
newScan = tScan{:}
I get the error 'Undefined function or variable 'x'.'
.......................................................
3- The problem is, even with using col =1, the content of
col=getappdata(0,'edit16');
G=newScan(:,col);
set(handles.edit18,'string',G);
is not purely the content of the 1st column but it shows the 1st values of the 1st, 4th, 7th columns of the nine-column file. So, I think there is a probelm with reading the text file by
tScan = textscan(x, '%s %f %s','headerlines',1);
right?
The number of format items you have in the '%s %f %s' section should match the number of columns in the file, even if you will never need those columns. If you know you will not need the columns you can use %*s controls. For example '%s%f%s%*s%*s%*s%*s%*s%*s'
But how about if the number of column is not the same all the time?
tScan = textscan(x, '%s%f%s%*[^\n]'. 'HeaderLines', 1);
That will cause it to skip everything after the third column until the next newline character.
Thanks a lot. But the selection of the desired column is random as it may take any value not only the second column. Your suggestion works perfect for
set(handles.edit_tauexp,'string',data);
in the following (complete) code
% tScan = textscan(x, '%s %f %s','headerlines',1);
tScan = textscan(x, '%s%f%s%*[^\n]', 'HeaderLines', 1);
newScan = tScan{:,:};
data=newScan;
set(handles.edit_tauexp,'string',data);
% another section to update from an edit box
data1 =get(handles.edit_T,'String');
data1 = cellstr(data1);
set(handles.edit_Texp,'string',repmat(data1,1379,1));
% third section to look for a certain column index and print its content in a list box
col=getappdata(0,'edit16');
G=newScan(:,col);
set(handles.edit18,'string',G);
but for the last line the code it shows the error
Index exceeds matrix dimensions.
Error in gui3>pushbutton8_Callback (line 423)
G=newScan(:,col);
Even before using your suggestion and using the commented first line!
tScan = textscan(x, '%s%f%s%*[^\n]', 'HeaderLines', 1);
newScan = tScan{:,:};
Don't do that. The result of textscan() is a cell array with one entry for each item in the format specification that is not "*" . So in the above, %s%f%s is three non-* format items, so the output of textscan would be a 1 x 3 cell array. When you then use {:,:} on that and assign to a single output location, if you do not outright get an error, then newScan would get assigned the first of the results, equivalent to as if you had done
newScan = tScan{1,1};
which would be a cell column array of character vectors, one entry for the first field of each line that was parsed.
It would be possible to create an N x 3 cell array in which each row corresponded to one input line, with the columns corresponding to entries. To do that, you need to use
newScan = [tScan{1}, num2cell(tScan{2}), tScan{3}];

Sign in to comment.

More Answers (1)

Dears Jan and Walter, I solved the problem. I was using 'data' while with using the original 'tScan', it works fine.

Categories

Find more on App Building in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!