I'm creating a SIMULINK Library and I have made the following component:
And the function is:
function [m_out, Pt_out, Tt_out] = fcn(m_in, Pt_in, Tt_in)
coder.extrinsic('get_param')
PR = get_param('TURBO/Compressor Stage','PR');
DT = get_param('TURBO/Compressor Stage','DT');
m_out = m_in;
Pt_out = 0;
Pt_out = PR * Pt_in;
Tt_out = 0;
Tt_out = Tt_in + DT;
end
I would like the function to be able to access the block properties dynamically. Meaning that I would like to replace 'TURBO/Compressor Stage' with '[dynamic name of model]/[dynamic name of block]' (or something equivalent). Essentially, I would like the user of the library to be able to make their own model and use the component as many times as they need while setting the parameters independently.
Related
I am looking for some style/best practice advice. I often find myself writing scripts which need many (several tens of) parameters to be defined at the beginning. Then these parameters are used by many functions within the script. A minimum, simplified example might look something like the following:
params.var1 = 1;
params.var2 = 10;
params.var3 = 100;
params.var4 = 1e3;
result1 = my_func1(params);
result2 = my_func2(params);
Now, I don't want to pass many inputs into every function, so am reluctant to do something like result1 = my_func1(var1,var2,var3,var4,...). Therefore, I always find myself making each variable a field of a structure (e.g. params), and then passing this structure alone into each function, as above. The structure is not modified by the functions, only the parameters are used for further calculations.
One of the functions might look like this then:
function result = my_func1(params)
var1 = params.var1;
var2 = params.var2;
var3 = params.var3;
var4 = params.var4;
result = var1.^2 + var2.^2 -var3.^3 + var4;
end
Now, because I don't want to refer to each variable within the function as params.var1, etc. (in the interest of keeping the expression for result as clear as possible), I first do all this unpacking at the beginning using var1 = params.var1.
I suppose the best thing to be doing in situations like this might be to use classes (because I have some data and also want to perform functions on that data). Are there any better ways for me to be doing this kind of thing without moving fully to object-oriented code?
I would simply leave the unpacking out. Call the struct params something shorter inside the function, to keep clutter to a minimum:
function result = my_func1(p)
result = p.var1.^2 + p.var2.^2 - p.var3.^3 + p.var4;
end
I would keep calling it params elsewhere, so you don’t have to deal with cryptic names.
You can define constant functions:
function out = var1
out = 1;
end
function out = var2
out = 10;
end
function result = my_func1
result = var1.^2 + var2.^2;
end
Based on your actual application you may pass array of numbers:
var = [var1 var2 var3 var4];
my_func1(var);
my_func1(var1,var2,var3,var4,...) in my opinion is preferred over passing struct.
I have a segment of code where a composition of nested loops needs to be run at various times; however, each time the operations within the nested loops are different. Is there a way to make the outer portion (loop composition) somehow a functional piece, so that the internal operations are variable. For example, below, two code blocks are shown which both use the same loop introduction, but have different purposes. According to the principle of DRY, how can I improve this, so as not to need to repeat myself each time a similar loop needs to be used?
% BLOCK 1
for a = 0:max(aVec)
for p = find(aVec'==a)
iDval = iDauVec{p};
switch numel(iDval)
case 2
r = rEqVec(iDval);
qVec(iDval(1)) = qVec(p) * (r(2)^0.5 / (r(1)^0.5 + r(2)^0.5));
qVec(iDval(2)) = qVec(p) - qVec(iDval(1));
case 1
qVec(iDval) = qVec(p);
end
end
end
% BLOCK 2
for gen = 0:max(genVec)-1
for p = find(genVec'==gen)
iDval = iDauVec{p};
QinitVec(iDval) = QinitVec(p)/numel(iDval);
end
end
You can write your loop structure as a function, which takes a function handle as one of its inputs. Within the loop structure, you can call this function to carry out your operation.
It looks as if the code inside the loop needs the values of p and iDval, and needs to assign to different elements of a vector variable in the workspace. In that case a suitable function definition might be something like this:
function vec = applyFunctionInLoop(aVec, vec, iDauVec, funcToApply)
for a = 0:max(aVec)
for p = find(aVec'==a)
iDval = iDauVec{p};
vec = funcToApply(vec, iDval, p);
end
end
end
You would need to put the code for each different operation you want to carry out in this way into a function with suitable input and output arguments:
function qvec = myFunc1(qVec, iDval, p)
switch numel(iDval)
case 2
r = rEqVec(iDval); % see note
qVec(iDval(1)) = qVec(p) * (r(2)^0.5 / (r(1)^0.5 + r(2)^0.5));
qVec(iDval(2)) = qVec(p) - qVec(iDval(1));
case 1
qVec(iDval) = qVec(p);
end
end
function v = myFunc2(v, ix, q)
v(ix) = v(q)/numel(ix);
end
Now you can use your loop structure to apply each function:
qvec = applyFunctionInLoop(aVec, qVec, iDauVec, myFunc1);
QinitVec = applyFunctionInLoop(aVec, QinitVec, iDauVec, myFunc2);
and so on.
In most of the answer I've kept to the same variable names you used in your question, but in the definition of myFunc2 I've changed the names to emphasise that these variables are local to the function definition - the function is not operating on the variables you passed in to it, but on the values of those variables, which is why we have to pass the final value of the vector out again.
Note that if you want to use the values of other variables in your functions, such as rEqVec in myFunc1, you need to think about whether those variables will be available in the function's workspace. I recommend reading these help pages on the Mathworks site:
Share Data Between Workspaces
Dynamic Function Creation with Anonymous and Nested Functions
Lets say we have a custom extractor function
[features,featureMetrics] = exampleBagOfFeaturesExtractor(img,param1, param2)
I want to call bagOfFeatures function and pass custom extractor function:
extractorFcn = #exampleBagOfFeaturesExtractor;
bag = bagOfFeatures(imgSets,'CustomExtractor',extractorFcn)
In exampleBagOfFeaturesExtractor function I want to use different local descriptors extractor depending on param1.
How do I pass param1 to exampleBagOfFeaturesExtractor?
What is the best way to use different local descriptors in my custom extractor function?
Thank you for your help!
Edit
This is the custom extractor function I am currently using:
function [features,featureMetrics] = exampleBagOfFeaturesExtractor(img,param1,param2)
keypoint_detector = cv.FeatureDetector(param1);
descriptor_extractor = cv.DescriptorExtractor(param2);
kpts = keypoint_detector.detect(img);
[ features, kpts ] = descriptor_extractor.compute(img, kpts);
featureMetrics=ones(1,size(features,1))/size(features,1);
end
The expected kind of functions that the bagOfFeatures function requires can only be a single input, namely the input image. Therefore, if you want to create a custom feature extractor where you can vary the parameters, you will need to first create the parameters, then create an anonymous function that captures these parameters via lexical closure. This means that when you create the anonymous function, make sure the parameters are created so that when you reference them in your anonymous function, they capture the most up to date version of the parameters prior to creating the function.
Therefore, assuming param1 and param2 already exist in your workspace, create a function like so:
% Create param1 and param2 here
param1 = ...;
param2 = ...;
extractorFcn = #(img) exampleBagOfFeaturesExtractor(img, param1, param2);
This creates an anonymous function that takes in a single input - your image. param1 and param2 are thus captured in your function, so the state of the variables is recorded and are made available within the anonymous function. Also note that the function doesn't take in additional inputs, only the input image. You can then call bagOfFeatures as normal. However, should you want to change param1 or param2, not only will you have to change these parameters, but you must re-declare the anonymous function again so that the latest stage of the variables is recaptured.
As a quick example, suppose I've created an anonymous function like so:
x = 5;
y = #(t) t + x;
This function y takes the current state of x and adds it with a variable t. For now, this acts like how we expect it:
>> x = 5;
>> y = #(t) t + x;
>> y(6)
ans =
11
We put in the value 6 and we get 11. If we try and change x then call y, it will not change this in the function as it captured the state of the variable before you created the function:
>> x = 10;
>> y(6)
ans =
11
Therefore, if you want to change the parameters, you must also re-declare the function again before calling bagOfFeatures, so:
param1 = ...; % Change this to something new
param2 = ...; % Change this if you like as well
extractorFcn = #(img) exampleBagOfFeaturesExtractor(img, param1, param2);
In MATLAB terms, these variables persist in the anonymous function. You can read more about it here: https://www.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html#f4-71621
I have a function but I cannot deal with the variable named data when I call the function. If I run the code alone (without calling the function, it works).
Please find the actual code below:
function data = returns_ext(input);
clear all
clc
ticker = 'BA';
filename = ['C:\Users\FP\Documents\MatlabCode\P\prices\' ticker 'daily.csv'];
newData1 = importdata(filename);
% Create new variables in the base workspace from those fields.
vars = fieldnames(newData1);
for i = 1:length(vars)
assignin('base', vars{i}, newData1.(vars{i}));
end
prices_data = data;
ERROR: At compilation, "data" was determined to be a variable and this
variable is uninitialized. "data" is also a function name and previous versions of MATLAB would have
called the function.
However, MATLAB 7 forbids the use of the same name in the same
context as both a function and a variable.
Error in ==> returns_ext at 17
prices_data = data;
You should replace assignin by eval, since assignin assigns either in the caller function calling returns_ext or the base workspace. See the simple example below:
function test
newData1.prices = 1;
newData1.dates = 2;
variables = {'prices','dates'};
for i = 1:length(variables)
temp = newData1.(variables{i});
eval([variables{i} ' = temp;']);
end
disp(prices)
disp(dates)
If the data is available in 'base' workspace then you need to update your code as this:
data = eval('base','data;');
prices_data = data;
i want to build a class like that:
classdef myclass < handle
properties
v1 = struct('value', 100)
v2 = struct('value', 200);
end
methods
function plusone(obj, vars) % SHOULD BE MODIFIED SOMEHOW??
vars.value = vars.value + 1;
end
end
end
And my question is, how should i write the method plusone so in Command Window i can choose which property i want to modify, i.e. i choose to modify property v2:
a = myclass();
a.plusone(a.v2);
that update the field value of variable v2 of object a ? Or is there a problem with my thinking method?
Yes, you can create a method like that, though you need to pass the reference to the field differently:
methods
function plusone(obj, propName)
obj.(propName).value = obj.(propName).value + 1;
end
end
To call the method, pass the reference as string:
a = myclass();
a.plusone('v2')