Matlab: How to remove the error of non-existent field - matlab

I am getting an error when running matlab code. Here I am trying to use one of the outputs of previous code as input to my new code.
??? Reference to non-existent field 'y1'.
Can anyone help me?

A good practice might be to check if the field exists before accessing it:
if isfield( s, 'y1' )
% s.y1 exists - you may access it
s.y1
else
% s.y1 does not exist - what are you going to do about it?
end
To take Edric's comment into account, another possible way is
try
% access y1
s.y1
catch em
% verify that the error indeed stems from non-existant field
if strcmp(em.identifier, 'MATLAB:nonExistentField')
fprintf(1, 'field y1 does not exist...\n');
else
throw( em ); % different error - handle by caller?
end
end

Have you used the command load to load data from file(s)?
if yes, this function overwrite your current variables, therefore, they become non-existent, so when you call, it instead of using:
load ('filename');
use:
f=load ('filename');
now, to refer to any variable inside the loaded file use f.varname, for
example if there is a network called net saved within the loaded data you may use it like:
a = f.net(fv);

I would first explain my situation and then give the solution.
I first save a variable op, it is a struct , its name is coef.mat;
I load this variable using coef = load( file_path, '-mat');
In a new function, I pass variable coef to it as a parameter, at here, the error Reference to non-existent field pops out.
My solution:
Just replace coef with coef.op, then pass it to the function, it will work.
So, I think the reason behind is that: the struct was saved as a variable, when you use load and want to acess the origin variable, you need point it out directly using dot(.) operation, you can directly open the variable in Matlab workspace and find out what it wraps inside the variable.
In your case, if your the outputs of previous code is a struct(It's my guess, but you haven't pointed out) and you saved it as MyStruct, you load it as MyInput = load(MyStruct), then when use it as function's parameter, it should be MyInput.y1.
Hops it would work!

At first load it on command window and observe the workspace window. You can see the structure name. It will work by accessing structure name. Example:
lm=load('data.mat');
disp(lm.SAMPLE.X);
Here SAMPLE is the structure name and X is a member of the structure

Related

Matlab loop: ignores variable definition when loading something from directories

I am new to MATLAB and try to run a loop within a loop. I define a variable ID beforehand, for example ID={'100'}. In my loop, I then want to go to the ID's directory and then load the matfile in there. However, whenever I load the matfile, suddenly the ID definition gets overridden by all possible IDs (all folders in the directory where also the ID 100 is). Here is my code - I also tried fullfile, but no luck so far:
ID={'100'}
for subno=1:length(ID) % first loop
try
for sessno=1:length(Session) % second loop, for each ID there are two sessions
subj_name = ([ID{subno} '_' Session{sessno} '_vectors_SC.mat']);
cd(['C:\' ID{subno} '\' Session{sessno}]);
load(subj_vec_name) % the problem occurs here, when loading, not before
end
end
end
When I then check the length of the IDs, it is now not 1 (one ID, namely 100), but there are all possible IDs within the directory where 100 also lies, and the loop iterates again for all other possible IDs (although it should stop after ID 100).
You should always specify an output to load to prevent over-writing variables in your workspaces and polluting your workspace with all of the contents of the file. There is an extensive discussion of some of the strange potential side-effects of not doing this here.
Chances are, you have a variable named ID inside of the .mat file and it over-writes the ID variable in your workspace. This can be avoided using the output of load.
The output to load will contain a struct which can be used to access your data.
data = load(subj_vec_name);
%// Access variables from file
id_from_file = data.ID;
%// Can still access ID from your workspace!
ID
Side Note
It is generally not ideal to change directories to access data. This is because if a user runs your script, they may start in a directory they want to be in but when your program returns, it dumps them somewhere unexpected.
Instead, you can use fullfile to construct a path to the file and not have to change folders. This also allows your code to work on both *nix and Windows systems.
subj_name = ([ID{subno} '_' Session{sessno} '_vectors_SC.mat']);
%// Construct the file path
filepath = fullfile('C:', ID{subno}, Session{sessno}, subj_name);
%// Load the data without changing directories
data = load(filepath);
With the command load(subj_vec_name) you are loading the complete mat file located there. If this mat file contains the variable "ID" it will overwrite your initial ID.
This should not cause your outer for-loop to execute more than once. The vector 1:length(ID) is created by the initial for-loop and should not get overwritten by subsequent changes to length(ID).
If you insert disp(ID) before and after the load command and post the output it might be easier to help.

Callback sharing data in Matlab

I have being to share data between several callback options in Matlab, however no succes so far. I have a gui with multiple tables which I use to get the input from the user. I have multiple callback functions for the different tables. I would like to use the data from table 1 and callback 1 together with the date in table 2 in callback two.
function MaterialProperties(Material, Data)
Material_data = get(Material, 'Data');
% Avoid bluehighlight in table
set(Material,'Data',{'dummy'});
set(Material,'Data', Material_data);
% Store variable in workspace
assignin('base','Material_data',Material_data)
%Mat_data = guidata(gcbo);
%for i=1:size(Material_data,2)
% Mat_data.MatData{i}=Material_data{i};
%end
% Save the change you made to the structure
guidata(gcbo,Mat_data)
assignin('base','Mat_data',Mat_data)
end
function Stacking_sequence(Layup, Data)
% I want to use the date (Material_data) of MaterialProperties here in this callback
layup_data = get(Layup, 'Data');
%overwrite data with a dummy and restore the old data afterwards, to force deselection
set(Layup,'Data',{'dummy'});
set(Layup,'Data', layup_data );
%store variable in workspace
assignin('base','layup_data',layup_data)
layup = strsplit(layup_data{1,1},'\');
assignin('base','layup',layup)
end
Can anyone help. I tried theMatlab help, but the suggestions stated there didn't work (maybe I implemented it wrong)
It looks like you simply need to retrieve the handles structure at the beginning of callback 2, like you did in the first callback:
Mat_data = guidata(gcbo);
after which it should be available in the 2nd callback. By the way this very line and the 3 lines following it are commented in your code is that a mistake?
Alternative solution:
As an alternative solution, you can use setappdata/getappdata to share data between function callbacks as well as in the command window, depending on where you store those data.
For example, if you save Material_data at the end of the 1st callback using something like this:
setappdata(0,'MatData',Material_Data); % Save in the Matlab root 0 (accessible everywhere), and give some dummy name)
Then at the beginning of the 2nd callback, you can retrieve the data using getappdata:
Material_Data = getappdata(0,'MatData');
and you're good to go. Instead of using the 0 root, you could also store the data in the GUI itself, using for example handles.FigureGUI or whatever the name of the figure is. Then the data would be available only if the figure is not closed/deleted. Play around with those and see what you prefer.
Hope that helps!

Matlab saving without losing previous iteration's value

i'm trying to save values of iterations in a loop. After this function, they will execute other functions before coming to the next iteration. But the problem i'm facing is, it overwrites them and bcomes 000000. Only the last iteration values are seen. How can i fix it ? Is there a way not to use the same variable and save them ? i read about append but will have to use different var name n is not really nice to do so.
function DistanceMatrix(iteration,distance_row)
load('data.mat','oridata')
load('centroids.mat','centroids')
for i = distance_row:(distance_row+3)
for j=1:300 %no.genes
total=0;
for k=1:6
total=total+((oridata(j,k)- centroids(i,k))^2);
end
DistMatrix_Val(i,j)=sqrt(total);
end
end
save('DistanceMatrix.mat','DistMatrix_Val')
DistMatrix_Val;
GroupMatrix(iteration,distance_row)
end
This is the output. I WOULD LIKE TO STORE ALL ITERATION's value and not overwrite them. Can any1 help ?
OK. Use
load('DistanceMatrix.mat','DistMatrix_Val')
or
persistent DistMatrix_Val
just before the first load command you showed to us.
I think this is what you should do:
functon DistanceMatrix = DistanceMatrix(iteration,distance_row)
Rather than saving the variable at the end of the function, you return it.
After returning it you can include the variable in a bigger variable (for example a three dimensional Nx4x300 matrix)
If neccesary you can then save it at the end.

Calling the function doesn't work

I have a cell array of stucts, each containing the personalia of a person. I put it into this function to get them listed in a text file of a chosen name.
function store( filename, persons )
fid = fopen(filename,'w');
for i=1:length(persons)
fprintf(fid, '%s',serialize_person(persons{i}));
end
Now this function works fine: I enter a <1x3 cell> and get out a text file with three listed persons. However, I want to call this function from another:
function process_store()
list=input('Write in the list of persons you want listed: ');
fprintf('\n')
newfile=input('Give the text file a name: ','s');
store(filename,list)
end
Here I enter the name of the <1x3 cell> as before, but I get a error message "Error using input,Undefined function or variable 'persons'."
Why is this? Am I not using the exact same data as Im using in 'store'?
The problem is that the variable persons isn't accessible inside the function process_store. In Matlab (and most other programming languages) functions can't access variables defined in their calling functions. To understand this better, I recommend having a read of the Wikipedia article on levels of scope.
You essentially have two options here:
Make persons a global variable, both in your workspace and in the function process_store, by using the declaration global persons. I wouldn't recommend this.
Use the function evalin to allow process_store to access variables in its parent workspace.
I'd go with option 2 if I were you. It's a little tricky, so let me explain how it works. Let's create a variable persons in the global workspace.
>> persons = {'John', 'Jack', 'Jill'};
Now say we have the following function
function example()
x = input('Give me a variable name: ');
disp(x)
end
What happens if we try to use it?
>> example()
Give me a variable name: persons
Error using input
Undefined function of variable 'persons'
Error in example (line 2)
x = input('Give me a variable name: ');
Oh dear. That's because the function example doesn't have access to the global workspace, which is where persons is defined. But instead, we can store the name of the variable we want to access, and then check out its value in the global workspace by using evalin, like this
function example()
s = input('Give me a variable name: ', 's');
x = evalin('caller', s);
disp(x)
end
Now if we use it:
>> example()
Give me a variable name: persons
'John' 'Jack' 'Jill'
It works as we expected! Great!
Massive disclaimer
There is almost never a good reason to use functions like evalin (or eval, or assignin or any other function that messes around executing strings as code). There's almost certainly a better way of doing what you want to do. But without knowing what it is you're trying to do, it's hard to give you better advice.
At the prompt
Write in the list of persons you want listed:
if you typed
persons
then you would get exactly that error message if the variable persons was not defined.

Programmatically save changes of an editable uitable

I created an UItable in Matlab which I fill with various values and options.
It looks like:
the corresponding code is the following:
selector_1 = { 'A'; 'B' ; 'C' };
selector_2 = { 'A.1'; 'A.2'; 'A.3'; ...
'B.1'; 'B.2'; 'B.3'; ...
'C.1'; 'C.2'; 'C.3' };
rows = 5;
f = figure('name','Configuration of output','Position',[200 200 430 25+rows*20],'numbertitle','off','MenuBar','none');
dat = {'select outputfile...', 'select identifier...', 'Specifier', 'Index'};
dat = repmat(dat,rows,1);
columnname = {'Output file ',...
'Identifier ',...
'Specifier ', 'Index'};
columnformat = { {selector_1{:}}, {selector_2{:}}, 'char', 'numeric' };
columneditable = [true true true true];
t = uitable('Units','normalized','Position',...
[0 0 1 1], 'Data', dat,...
'ColumnName', columnname,...
'ColumnFormat', columnformat,...
'ColumnEditable', columneditable,...
'RowName',[]);
set(t, 'Data', dat,'celleditcallback','get(t,''Data'')');
So I run the code and the figure is open. The underlying script has therefore finished.
When I now edit the table my uitable object is changed and after I finished I can get my final configuration with:
finalconfig = get(t,'Data');
But the thing is I need manually type this line, because my script has already finished. If I put this line at the end of my script, I get an error.
So I thought about using the following loop, to detect when I close the table and to store the last configuration
while ~isempty(findobj('name','Configuration of output'))
% some action
end
finalconfig = get(t,'Data');
And I tried everything to put inside the loop, the whole script, just the set command including the celleditcallback, and other things, but nothing worked. Either my script get stucked inside the loop or the display of my table is not updated when I edit a value. I also tried drawnow at different positions. How one handles this situation? How can I automatically store my final results?
I assume "closing the window" is the best action to detect, as I don't think I could implement a "save" button. I also tried to create a gui using GUIDE but got completely lost, I hope to solve it without.
Edit:
I was now able to implement a "save"-button and tried the callback as follows:
uimenu('Label','Save configuration','Callback',#saveConfig);
function saveConfig(~,~)
output = get(t,'Data',);
save([pwd 'output.mat'],'output');
end
also I implemented a custom CloseRequestFcn as suggested by Lucius Domitius Ahenobarbus. But then I have either one of the following problems:
1)
I define everything as a script, everything works fine, but I need to define functions like #saveConfig (actually my favorite) or #my_Closefcn as a unique function-file in my workspace and I have a hard time to pass the right parameters as dat always remains the same, even though it actually gets changend.
(The example from the mathworks site works! But it doesn't need additional parameters.)
2) When I use
function configuration
% my script from above
end
I can implement #saveConfig or #my_Closefcn directly (nested) and I guess the passing of the parameters would work fine. But the editing of my table does not work anymore, throwing the following error:
Error using handle.handle/get
Invalid or deleted object.
Error while evaluating uitable CellEditCallback
How to solve that?
Now that I know that I can even add buttons to an uitable I REALLY like to avoid GUIDE.
My code above is executable, so I'd be glad if you try it to see what my actual problem is, as it is hard to describe.
depending on using GUIDE or not:
use the CloseRequestFcn->
without GUIDE use:
%write your own CloseRequestFcn and set the figure CloseRequest-Callback to it:
set(gcf,'CloseRequestFcn',#my_closefcn)
%use gcf or the handle of the figure directly
and define my_closefcn including a delete statement for the figure-handle, else the figure will not close :)
See the docs for more information about "Redefining the CloseRequestFcn".
with GUIDE:
you can edit the CloseRequestFcn by inspecting the figure. There is a field called CloseRequestFcn that will create the function automatically and you dont need to take care about getting the handle. It will look like this:
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: delete(hObject) closes the figure
delete(hObject);
Now BEFORE deleting the figure, you should be able to get the data of the uitable (if you have the handle) and I would suggest to just assign the data to the base workspace, like:
assignin('base', 'finalTableData', get(myTableHandle,'Data'));
EDIT
as I was not clear enough, see this example:
(use within one single script)->
function test
h=figure;
x=1:10;
mytable=uitable(h,'Data',x);
set(h,'CloseRequestFcn',#myCloseFcn)
%give a unique Tag:
set(h,'Tag', 'myTag')
set(mytable,'Tag','myTableTag')
end
function myCloseFcn(~,~)
myfigure=findobj('Tag','myTag');
myData=get(findobj(myfigure,'Tag','myTableTag'),'Data')
assignin('base','myTestData',myData)
delete(myfigure)
end
in fact, there is no need to take care for the parameters of your Closereq-Callback, if you know how to find the handle of the figure! Just give something to your figure/uitable that you are able to identify it later on. I used 'Tag', because the first thing I would think of, but there would be other parameters as well.
There are only two differences I can think of between running the code directly after the code, or inside the code.
1. Scope
Perhaps you are actually working with functions, rather than scripts. In this case the problem may be that inside your function, something you need is out of scope.
2. Timing
Though it is rare, sometimes the computer may seem to be finished, whilst it is actually still busy (for a few milliseconds or so).
Here are the steps to a general approach:
Make sure there is a trivial line at the place where you want to insert your command (1==1 for example)
Put a breakpoint at the line
Once matlab stops at the breakpoint, wait a second and try to run your command.
If it works I would bet on problem number 2. try placing a pause(1) before your command and see whether it helps.
If it doesn't work you are likely meeting problem number 1. Now it becomes a matter of finding the right place to put your command. And if the command cannot be put somewhere else in the code, perhaps try an ugly evalin(,'base'). However, the latter should really be considered a workaround rather than a solution.