Retain the value of loop variable even on making a call to another function in the loop - matlab

I want to preserve the value of variable q in the below mentioned code when it makes a call to the funtion gm.
demo.m is:
for q=1:Nqueries
disp(['Matching query ' db.queries{q}]);
qPath=[db.folder '/' db.fqueryFolder '/' db.queries{q} '_' featMethod '_' num2str(PeakThreshold) '.mat'];
fq=load(qPath);
query_path=[db.folder '/' db.queryFolder '/' db.queries{q} '.jpg'];
matches=cell(1,Nrefs);
fr=cell(1,Nrefs);
ref_paths=cell(1,Nrefs);
for r=1:Nrefs
rPath=[db.folder '/' db.frefFolder '/' db.references{r} '_' featMethod '_' num2str(PeakThreshold) '.mat'];
ref_paths{r}=[db.folder '/' db.refFolder '/' db.references{r} '.jpg'];
fr{r}=load(rPath);
%Matching things
[idx, dists] = vl_ubcmatch(fq.d,fr{r}.d,thRatio);
matches{r}.idx=idx;
matches{r}.dists=dists;
end
%We run the Generative Model
sim(q,:)=gm(query_path,ref_paths,fq,fr,matches,K);
end
and this code generates following error:
Matching query 1
??? Undefined function or variable 'q'.
Error in ==> gm at 86
Iq=imread(sprintf('db/queries/%d.jpg',q));
Error in ==> demo at 65
sim(q,:)=gm(query_path,ref_paths,fq,fr,matches,K);
The gm function uses q as follows:
Iq=imread(sprintf('db/queries/%d.jpg',q));

Adding more variables to the function call is the cleanest way of resolving this issue, of course. But if modifying the called function is too painful, e.g. because you'd have to change many functions until you reach the one where you want to use your variable, you might want to consider making this variable a global variable:
global YOURVARIABLE %choose a good name here to avoid
%overwriting existing global variables
YOURVARIABLE can now be accessed from any other function's workspace although you have to declare this in each function separately, see:
Declaring a global variable in MATLAB
Also, you should be very careful when using them:
http://www.mathworks.com/help/matlab/matlab_prog/share-data-between-workspaces.html
As described in the documentation global variables are risky because they have their own workspace that can be edited from anywhere, so if the same variable is used by several functions you might get unexpected results. Therefore, they should only be used when really necessary.

I modified the code in the for loop to
sim(q,:)=gm(query_path,ref_paths,fq,fr,matches,K,q);
and the definition of the called function gm as
gm(query_path,ref_paths,fq,fr,matches,K,q);

Related

save in for loop matlab

I am trying to save variables in a for loop. The following new variable can be created:
eval(['C' num2str(j) '=B']);
But I get an error while using this to save the variable by the following command :
save([dataDir, files(j).name],eval(['C' num2str(j) '=B']),'-append')
The error is : (Error: The expression to the left of the equals sign is not a valid target for an assignment.).
I wonder what is wrong with my approach and how can I save the changing variable name in changing file name in a for loop.
I will greatly appreciate your assistance.
There is an equal sign in your eval statement.
Can't you just save B?
do not use eval in a function itself.
save([dataDir, files(j).name],B,'-append')
Otherwise I would recommend storing the variable name itself
varname = sprintf('C%.0f',j)
eval([varname,'=B']);
save([dataDir, files(j).name],varname,'-append')

converge / over monadic function leads to scope error

I cant see to put converge (/) inside the function:
i:0
arg:0
{x+:1;i+:1}/[{i~0};0]
i ' Leads to answer 1
Works where i comes out to 1. The following segment will return an error:
depp:{[arg] i:0; {x+:1;i+:1}/[{i~0};0]; :i}
depp[0] ' Cant recognize i
Why?
you will either have to pass i to the lambdainside the function depp or use global assignment for i i.e
depp:{[arg] i::0; {x+:1;i+:1}/[{i~0};0]; :i}

undefined variable in matlab for a strcture

this is kind of lame but i am not able to remove this error. i have a function where i supply the name of a component which is an element inside the structure add_strcut.
so add_strcut has data_a , data_b etc.
and data_a has the field 'ode'. and again 'ode' has 'input'.
function bus_creator(component_name)
if (isfield(add_strcut.(component_name),'ode')==1)
for loop_out=1:length(add_strcut.(component_name).ode.input)
for loop_in=1:length(fieldnames(add_strcut.(component_name).ode.input{loop_out,2}))
struct_name=add_strcut.(component_name).ode.input{loop_out,2}.(char(fieldnames(add_strcut.(component_name).ode.input{loop_in,2})));
bus_creator_record(struct_name);
end
end
end
end
ofcourse here while calling the function i supply the component name as 'data_a'. but the second line throws me error.
the error is undefuned variable "add_strcut" or class "add_strcut.data_a"
even though when i use F9 to check the value it shows me fine but when i call this function it throws me this error
update
function bus_creator(main_component,component_name)
if (isfield(main_component.(component_name),'ode')==1)
for loop_out=1:length(main_component.(component_name).ode.input)
for loop_in=1:length(fieldnames(main_component.(component_name).ode.input{loop_out,2}))
struct_name=main_component.(component_name).ode.input{loop_out,2}.(char(fieldnames(main_component.(component_name).ode.input{loop_in,2})));
bus_creator_record(struct_name);
end
end
end
end
this is the updated function. now i will supply main_component='add_strcut' but now to access it as a variable i need to put main_component inside brackets but if i do that then it throws me error
at (main_component).(component_name)
it shows the dot in between in red and error is unexpected matlab operator
when passing the main structure don't use any quotes. just pass the structure name straight to the function without using ''.

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.

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

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