How to call an m file from another m file in MATLAB and retrieve an output? - file

I know this is a simple question, but for some reason I can't find a straight answer that works no matter where I look.
Basically, I have 4 values that were found in one m file, and I want to run them through a separate m file and retrieve the output from it.
I tried something like these, but none worked:
result = generate(nrow,ncol,a,b);
function result = generate(nrow,ncol,a,b);
result = #generate(nrow,ncol,a,b);
The final value in the m file "generate" is called result, and I'm trying to carry that across to my initial m file.
Any advice as to what I'm doing wrong would be greatly appreciated! Please and thank you

if your file generate.m defines a function it should have itself the following structure (which takes into account the fact that you have four returned values)
function [ret1 ret2 ret3 ret4] = generate(nrow,ncol,a,b)
.... % # Some processing of yours
ret1 = ... ; % # Returned values are eventually set
ret2 = ... ;
ret3 = ... ;
ret4 = ... ;
end
The function should be called (e.g. in your main script) as
[ret1 ret2 ret3 ret4] = generate(nrow,ncol,a,b);
now you have the variables ret1,ret2,ret3,ret4 available in the caller scope.
Be aware that the file generate.m must be in the current matlab PATH.

Related

Octave - How can I use pararrayfun with a file in input?

I am a new Octave user. My Octave version is 4.4.1.
I need help on how to use the parallel package.
I have a function modele_file that takes in as input a class structure that contains the path to files. I have to load that 'mat' files (see the code below).
The problem is that octave indicates that my entry is not defined.
I would be grateful if someone can help me find what is missing in my code
files = dir('./../data/*.mat');
[row col] = size(files);
for k = 1:1000
name{k} = getfield(files, {k,1}, 'name');
end
fun_str = #(stg) strcat("./../data/", stg) ;
vec_name = arrayfun(fun_str, name) ;
vec_result = arrayfun(fun_str, repmat({"result/"}, row,1)) ;
a = [vec_name, vec_result'] ;
struct_info = cell2struct(a, {"name", "result"}, 1);
solution = pararrayfun(nproc, modele_file, struct_info)
Here an example of my function :
function modele = modele_file(info_struct)
file = info_struct{1} ;
path = info_struct{2} ;
load(strcat(file)) ;
modele.X = zeros(2,2) ;
save('file.mat', 'modele') ;
Although my function is able to work. My priority is to launch my function, I do not specifically need it to register in an object.
Thank you.

matlab save create directory if doesn't exist

I am trying to write a MATLAB function that extends the "save" command to create the specified path if it doesn't already exist. I have been successful with a single variable, but not with multiple variables. With multiple variables, I receive the following error message:
31 variables_to_save(i) = variable_name;
Conversion to cell from char is not possible.
Error in saveMatVars (line 31)
variables_to_save(i) = variable_name;
Here is my function:
function saveMatVars( file_path, varargin )
%saveMatVars saves variables in varargin to file specified in file_path, creating the file path if it doesn't exist
% varargin is the variables to save
% get path and filename from file_path
[parent_folder, ~] = fileparts(file_path);
% if parent_folder doesn't exist, create it
if ~exist(parent_folder, 'dir')
mkdir(parent_folder);
end
% get names of variables to save
num_vars = length(varargin);
switch num_vars
case 0
return
case 1
variable_name = inputname(2);
variable_name = matlab.lang.makeValidName(variable_name);
variable_val = varargin{1};
feval(#()assignin('caller', variable_name, variable_val)); % create
a dummy function so I can access the current function's workspace
variables_to_save = variable_name;
otherwise % note - this part does not work
variables_to_save = cell(1,1);
for i = 1:num_vars
variable_name = inputname(i+1);
variable_name = matlab.lang.makeValidName(variable_name);
variable_val = varargin{i};
feval(#()assignin('caller', variable_name, variable_val)); % create a dummy function so I can access the current function's workspace
variables_to_save(i) = variable_name;
end
variables_to_save = string(variables_to_save);
end
% save variables_to_save in file_path
save(file_path, variables_to_save);
return
end
The documentation on "save" says the following about the variables to save:
save(filename,variables) saves only the variables or fields of a structure array specified by variables.
I have tried various functions for converting char arrays to strings and to cell arrays to no avail.

How to use IDL's min() function's min_subscript argument in for loop?

I have experience in python but am new to IDL. I am trying to write a function that will return two bins. I want to use the min function to get my bin edges. My issue is that I am trying to use the min_subscript argument to denote each bin edge, and I can't figure out how to do this in a for loop. I want to write my code so that each loop has 2 different min_subscript variables (the two edges of the bin), and these variables are written into their own arrays. Here is my code:
FUNCTION DBIN, radius, data, wbin, radbin, databin
FOR i = 0, N_ELEMENTS(radius)-1 DO BEGIN
l = lonarr(N_ELEMENTS(radius))
m = lonarr(N_ELEMENTS(radius))
junk1 = min(abs(radius - radius[i]), l[i])
junk2 = min(abs(radius - (radius[i] + wbin)), m[i])
radbin = lonarr(N_ELEMENTS(radius))
radbin[i] = radius[l[i]:m[i]]
databin = lonarr(N_ELEMENTS(data))
databin[i] = total(data[l[i]:m[i]])
ENDFOR
END
wbin is the desired bin width. The junk variables only exist for the purpose of getting the min_subscripts at those locations. The min_subscripts are the l[i]'s and the m[i]'s.
I appreciate any help!!
The min_subscript argument is trying to pass a value back to you, so you must pass a "named variable" to it. Named variables have pass by reference behavior. So you have to do it in two steps, something like:
junk1 = min(abs(radius - radius[i]), li)
l[i] = li
Above, li is a named variable, so it can receive and pass back the value. Then you can put it in your storage array.

Array of structures in MATLAB Simulink

I am trying to create an array of structures in Simulink and got some problems with it.
first of all i tried to create it directly in Simulink using this:
function a = fcn(Dibhole, t , x, const)
%#codegen
%Output = zeros(10,10);
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
a = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
a(i,j).number = 0;
a(i,j).move = 0;
end
end
and i got this error:
Derived output was of type struct. 'Inherited type' is unsupported for this
type and a defined bus object must be used instead. Click on 'a' and
set data type for 'a' to be 'Bus: ', where '' is
the name of a bus object from the MATLAB workspace.
So i found some example how to create struct in Matlab and receive this to Simulink: http://blogs.mathworks.com/seth/2011/12/05/initializing-buses-using-a-matlab-structure/
That works perfectly but i still can't repeat this with array:
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
myStruct2 = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
myStruct2(i,j).number = 1;
myStruct2(i,j).move = 1;
end
end
busInfo = Simulink.Bus.createObject(myStruct2);
Can anyone clarify to me what's the problem? Or maybe there is different way to create array of struct in Simulink?
Mihail
Simulink wants you to define the output of the function to be a bus.
As 'Bus: My_test_bus', for example.
Take a look at the Simulink Bus Editor. You can find it in any model under the menu, Edit->Bus Editor.
This would be a good start.
Rick, i think you are right!
i have tried this problem for a long time, and have got this results:
the irony is that I was never able to create array of structures BUT i did this with structure of arrays! :D
I made this steps for it:
to use structure of arrays we need to define and initialize it in some MATLAB function. Like this:
number = zeros(10,1);
move = zeros(10,1);
for i = 1:10
number(i,1) = i+1;
move(i,1) = i+2;
end
a = struct('numbers',number,'movement', move);
To work this data we must use Bus Selector.
So we have array in "numbers" and "movement".
BUT! Here we go, Rick: we must define type of output of MATLAB function like Bus! How to do this in simulink? i found this way:
in model properties in simulink Callbacks/PreLoadFcn define some function and in same folder as project create .m file named like this just defined function.
In this file create structure of array and define Bus type for it:
number = zeros(10,1);
move = zeros(10,1);
a = struct('numbers',number,'movement', move);
busInfo = Simulink.Bus.createObject(a);
Now we have Bus type for our structure at first loading of simulink model.
Last step: define MATLAB function output type directly.
in Model Explorer choose your MATLAB function. choose output variable. Set DataType for it: Bus:slBus1 (the name of this Bus type you can see in wokspace of matlab, because its a global variable).
That's all! now it works!
(tried to add pictures, but i have no enough reputation :( )
Now my program works in this way, but i also tried to create array of structures and still have the problems. i tried to create Bus for it, but can't transmit it to Bus Selector - it doesn't know what to do with structures... i also tried to add one more MATLAB function to create some data from structures and then display it, but it doesn't works too(

Matlab, timed iteration over a matrix

I'm developing a simulator of sorts as a hobby project. The specific function i'm having trouble with takes a row from a matrix and supplies to a function every 50'th millisecond, but I'm a novice with Matlab scripting and need some help.
Each time the timer clicks, the next row in the matrix should be supplied to the function "simulate_datapoint()". Simulate_datapoint() takes the row, performs some calculation magic and updates a complex "track" object in the tracks array.
Is this a completely backwards way of trying to solve this problem or am I close to a working solution? Any help would be greatly appreciated.
Here's what I have right now that doesn't work:
function simulate_data(data)
if ~ismatrix(data)
error('Input must be a matrix.')
end
tracks = tracks_init(); % create an array of 64 Track objects.
data_size = size(data,1); % number of rows in data.
i = 0;
running = 1;
t = timer('StartDelay', 1, 'Period', 0.05, 'TasksToExecute', data_size, ...
'ExecutionMode', 'fixedRate');
t.StopFcn = 'running = 0;';
t.TimerFcn = 'i = i+1; simulate_datapoint(tracks, data(i,:));';
disp('Starting timer.')
start(t);
while(running==1)
% do nothing, wait for timer to finish.
end
delete(t);
disp('Execution complete.')
end
You're very close to a working prototype. A few notes.
1) Your string specified MATLAB functions for the timerFn and stopFn don't share the same memory address, so the variable "i" is meaningless and not shared across them
2) Use waitfor(myTimer) to wait... for the timer.
The following code should get you started, where I used "nested functions" which do share scope with the calling function, so they know about and share variables with the calling scope:
function simulate
iterCount = 0;
running = true;
t = timer('StartDelay', 1, 'Period', 0.05, 'TasksToExecute', 10, ...
'ExecutionMode', 'fixedRate');
t.StopFcn = #(source,event)myStopFn;
t.TimerFcn = #(source,event)myTimerFn;
disp('Starting timer.')
start(t);
waitfor(t);
delete(t);
disp('Execution complete.')
% These are NESTED functions, they have access to variables in the
% calling function's (simulate's) scope, like "iterCount"
% See: http://www.mathworks.com/help/matlab/matlab_prog/nested-functions.html
function myStopFn
running = false;
end
function myTimerFn
iterCount = iterCount + 1;
disp(iterCount);
end
end

Resources