Setting datajoint key to a different variable in make fxn - datajoint

Wondering why and when it's needed to set the key to a different variable in a make/maketuples function in an auto-populated table in datajoint, as in the documentation here.
In this example, the part table SegmentationROI is defined as follows:
%{
# Region of interest resulting from segmentation
-> test.Segmentation
roi : smallint # roi number
---
roi_pixels : longblob # indices of pixels
roi_weights : longblob # weights of pixels
%}
classdef SegmentationROI < dj.Part
properties(SetAccess=protected)
master = test.Segmentation
end
methods
function make(self, key)
image = fetch1(test.Image & key, 'image');
[roi_pixels, roi_weighs] = mylib.segment(image);
for roi=1:length(roi_pixels)
entity = key;
entity.roi_pixels = roi_pixels{roi};
entity.roi_weights = roi_weights{roi};
self.insert(entity)
end
end
end
end
What is the purpose of renaming the key as a separate variable, entity (entity = key), and then inserting that?

In this case, we're adding fields to entity as a struct. I'd consider it best practice to preserve arguments a function as-is. If we added a second for-loop here, we might run into issues when calling key for another purpose.
Caveat: I'm more familiar with DataJoint python and have not used it extensively in MATLAB.

Related

Loop in object creation and declaration with annotations

I need to use a loop to create multiple objects in my model declaration.
For loops do not seem to work outside an "equation" or an "algorithm" block.
I need to declare my objects in the beggining of the Model.
I also need to add different annotation to each object so that the location of each object differs.
As a result i want to create a tank consisting of cellConst subparts (found in Thermocycle package).
I already tried to do so by using the following code:
model MyTank
CellConst [N] cellConstArray = {
CellConst (
Ai=0.53,
Ac=0.88,
Mdotnom=1,
L=0.25, Discretization=ThermoCycle.Functions.Enumerations.Discretizations.upwind_AllowFlowReversal, Vi=0.030, Tstart=293.15)
annotation (Placement(transformation(extent={{-14,22},{-8,28}})))
for i in 1:N
};
end MyTank;
I also tried a simple loop
model MyTank
for i in 1:N loop
end for;
end MyTank;
Though None of these two approaches worked.
Do you have any suggestions?
Thank you in advance.
You do things slightly differently in Modelica: you add modifiers to each element of the vector like this:
model MyTank
CellConst [N] cellConstArray(each Ai=0.53,
each Ac=0.88,
each Mdotnom=1,
each L=0.25,
each Discretization=ThermoCycle.Functions.Enumerations.Discretizations.upwind_AllowFlowReversal,
Vi = fill(0.030, N), // Just to show you can use an array here
each Tstart=293.15)
);
end MyTank;

Best way to select from several LUTs? (Modelica)

In our model of a physical system, we modify one flux value by a factor from a look-up table. The LUT itself is selected from a catalog of LUTs based on an integer index. We're currently loading the table data into CombiTable2D components. What is the correct way to select/define the correct LUT? If we have them all as named tables in one input data file, is there a way to pick an LUT based on it's tableName (the CombiTable parameter)? I've been playing with For loops in either equation or algorithm formats, but haven't found a syntax that works yet.
Thanks in advance for the thoughts...
I think it only works with one table per file so you can have an array of tables, something like:
parameter Integer N = 3;
parameter String selectTable = "tab2";
Modelica.Blocks.Tables.CombiTable2D tableArray[N](
each tableOnFile = true,
fileName = {"file1", "file2", "file3"},
tableName={"tab1", "tab2", "tab3"});
// use the tableArray
for i in 1:N loop
// note that N and selectTable need to be known at compile
// time so that the if and the for loop can be expanded
if (tableArray[i].tableName == selectTable)
then
connect(tableArray[i].u1, u1);
connect(tableArray[i].u2, u2);
connect(tableArray[i].y, y);
endif;
end for;

Matlab coder & dynamic field references

I'm trying to conjure up a little parser that reads a .txt file containing parameters for an algorithm so i don't have to recompile it everytime i change a parameter. The application is C code generated from .m via coder, which unfortunately prohibits me from using a lot of handy matlab gimmicks.
Here's my code so far:
% read textfile
string = readfile(filepath);
% do fancy rearranging
linebreaks = zeros(size(string));
equals = zeros(size(string));
% find delimiters
for n=1:size(string,2)
if strcmp(string(n),char(10))
linebreaks(n) = 1;
elseif strcmp(string(n), '=')
equals(n) = 1;
end
end
% write first key-value pair
idx_s = find(linebreaks);idx_s = [idx_s length(string)];
idx_e = find(equals);
key = string(1:idx_e(1)-1);
value = str2double(string(idx_e(1)+1:idx_s(1)-1));
parameters.(key) = value;
% find number of parameters
count = length(idx_s);
% write remaining key-value pairs
for n=2:count
key = string(idx_s(n-1)+1:idx_e(n)-1);
value = str2double(string(idx_e(n)+1:idx_s(n)-1));
parameters.(key) = value;
end
The problem is that seemingly coder does not support dynamic fieldnames for structures like parameters.(key) = value.
I'm a bit at a loss as to how else i am supposed to come up with a parameter struct that holds all my key-value pairs without hardcoding it. It would somewhat (though not completely) defeat the purpose if the names of keys were not dynamically linked to the parameter file (more manual work if parameters get added/deleted, etc.). If anybody has an idea how to work around this, i'd be very grateful.
As you say, dynamic fieldnames for structures aren't allowed in MATLAB code to be used by Coder. I've faced situations much like yours before, and here's how I handled it.
First, we can list some nice tools that are allowed in Coder. We're allowed to have classes (value or handle), which can be quite handy. Also, we're allowed to have variable sized data if we use coder.varsize to specifically designate it. We also can use string values in switch statements if we like. However, we cannot use coder.varsize for properties in a class, but you can have varsized persistent variables if you like.
What I'd do in your case is create a handle class for storing and retrieving the values. The following example is pretty basic, but will work and could be expanded. If a persistent variable were used in a method, you could even create a varsized allocated storage for the data, but in my example, it's a property and has been limited in the number of values it can store.
classdef keyval < handle %# codegen
%KEYVAL A key and value class designed for Coder
% Stores an arbitrary number of keys and values.
properties (SetAccess = private)
numvals = 0
end
properties (Access = private)
intdata
end
properties (Constant)
maxvals = 100;
maxkeylength = 30;
end
methods
function obj = keyval
%KEYVAL Constructor for keyval class
obj.intdata = repmat(struct('key', char(zeros(1, obj.maxkeylength)), 'val', 0), 1, obj.maxvals);
end
function result = put(obj, key, value)
%PUT Adds a key and value pair into storage
% Result is 0 if successful, 1 on error
result = 0;
if obj.numvals >= obj.maxvals
result = 1;
return;
end
obj.numvals = obj.numvals + 1;
tempstr = char(zeros(1,obj.maxkeylength));
tempstr(1,1:min(end,numel(key))) = key(1:min(end, obj.maxkeylength));
obj.intdata(obj.numvals).key = tempstr;
obj.intdata(obj.numvals).value = value;
end
function keystring = getkeyatindex(obj, index)
%GETKEYATINDEX Get a key name at an index
keystring = deblank(obj.intdata(index).key);
end
function value = getvalueforkey(obj, keyname)
%GETVALUEFORKEY Gets a value associated with a key.
% Returns NaN if not found
value = NaN;
for i=1:obj.numvals
if strcmpi(keyname, deblank(obj.intdata(i).key))
value = obj.intdata(i).value;
end
end
end
end
end
This class implements a simple key/value addition as well as lookup. There are a few things to note about it. First, it's very careful in the assignments to make sure we don't overrun the overall storage. Second, it uses deblank to clear out the trailing zeros that are necessary in the string storage. In this situation, it's not permitted for the strings in the structure to be of different length, so when we put a key string in there, it needs to be exactly the same length with trailing nulls. Deblank cleans this up for the calling function.
The constant properties allocate the total amount of space we're allowed in the storage array. These can be increased, obviously, but not at runtime.
At the MATLAB command prompt, using this class looks like:
>> obj = keyval
obj =
keyval with properties:
numvals: 0
>> obj.put('SomeKeyName', 1.23456)
ans =
0
>> obj
obj =
keyval with properties:
numvals: 1
>> obj.put('AnotherKeyName', 34567)
ans =
0
>> obj
obj =
keyval with properties:
numvals: 2
>> obj.getvalueforkey('SomeKeyName')
ans =
1.2346
>> obj.getkeyatindex(2)
ans =
AnotherKeyName
>> obj.getvalueforkey(obj.getkeyatindex(2))
ans =
34567
If a totally variable storage area is desired, the use of persistent variables with coder.varsize would work, but that will limit the use of this class to a single instance. Persistent variables are nice, but you only get one of them ever. As written, you can use this class in many different places in your program for different storage. If you use a persistent variable, you may only use it once.
If you know some of the key names and are later using them to determine functionality, remember that you can switch on strings in MATLAB, and this works in Coder.

Print the name of a variable on upon a plot/figure

Is it possible to refer back to/access the names of variables (say nx1 arrays) that make up a matrix? I wish to access them to insert there names into a plot or figure (as a text) that I have created. Here is an example:
A = [supdamp, clgvlv,redamp,extfanstat,htgvlv,occupied,supfanspd]
%lots of code here but not changing A, just using A(:,:)'s
%drawn figure
text(1,1,'supdamp')
...
text(1,n,'supfanspd')
I have failed in an attempt create a string named a with their names in so that I could loop through a(i,1), then use something like text(1,n,'a(i,1)')
Depending on your problem, it might make sense to use structures with dynamical field names.
Especially if your data in the array have some meaning other than just entries of a matrix in linear algebra sense.
# name your variables so that your grandma could understand what they store
A.('supdamp') = supdamp
A.('clgvlv') = clgvlv
...
fieldsOfA = fieldnames(a)
for n = 1 : numel(fieldsOfA )
text(1, n, fieldsOfA{n})
end

Is it possible to add methods on the fly to MATLAB classes?

Writing a subclass of dynamicprops allows to me to add properties dynamically to an object:
addprop(obj, 'new_prop')
This is great, but I would also love to create set / get functions for these properties on the fly. Or analysis functions that work on these dynamic properties.
My experience with Matlab has been so far, that once I create an instance of a class, adding new methods is not possible. That is very cumbersome, because my object may contain a lot of data, which I'll have to re-load every time that I want to add a new method (because I have to do clear classes).
So is there a way to add methods on the fly?
You cannot add methods like you add dynamic properties. However, there are two ways for implementing new methods during development that won't require you to re-load the data every time.
(1) I write standard methods as separate functions, and call them as myMethod(obj) during development. Once I'm sure they're stable, I add their signature into the class definition file - this requires a clear classes, of course, but it is a much delayed one, and from time to time you may have to shut down Matlab, anyway.
(2) With set/get methods, things are a little trickier. If you are using dynamicprops to add new properties, you can also specify their set/get methods, however (most likely, these methods/functions will want to receive the name of the property so that they know what to refer to):
addprop(obj,'new_prop');
prop = findprop(obj,'new_prop');
prop.SetMethod = #(obj,val)yourCustomSetMethod(obj,val,'new_prop')
EDIT
(2.1) Here's an example of how to set up a hidden property to store and retrieve results (based on jmlopez' answer). Obviously this can be improved a lot if you have a better idea what you're actually designing
classdef myDynamicClass < dynamicprops
properties (Hidden)
name %# class name
store %# structure that stores the values of the dynamic properties
end
methods
function self = myDynamicClass(clsname, varargin)
% self = myDynamicClass(clsname, propname, type)
% here type is a handle to a basic datatype.
self.name_ = clsname;
for i=1:2:length(varargin)
key = varargin{i};
addprop(self, key);
prop = findprop(self, key);
prop.SetMethod = #(obj,val)myDynamicClass.setMethod(obj,val,key);
prop.GetMethod = #(obj)myDynamicClass.getMethod(obj,key);
end
end
function out = classname(self)
out = self.name_;
end
end
methods (Static, Hidden) %# you may want to put these in a separate fcn instead
function setMethod(self,val,key)
%# have a generic test, for example, force nonempty double
validateattributes(val,{'double'},{'nonempty'}); %# will error if not double or if empty
%# store
self.store.(key) = val;
end
function val = getMethod(self,key)
%# check whether the property exists already, return NaN otherwise
%# could also use this to load from file if the data is not supposed to be loaded on construction
if isfield(self.store,key)
val = self.store.(key);
else
val = NaN;
end
end
end
end
I'm adding this answer because I think that this is not intuitive. At least not to myself at this moment. After finding this question I thought I had what I needed to be able to define the set/get methods for my dynamic class. All I wanted to achieve with this was something similar to what python does with its __setattr__ method. In any case, here is a continuation of the class made by #jonas a while ago with a few modifications to add the our custom set method.
classdef myDynamicClass < dynamicprops
properties (Hidden)
name_ %# class name
end
methods
function self = myDynamicClass(clsname, varargin)
% self = myDynamicClass(clsname, propname, type)
% here type is a handle to a basic datatype.
self.name_ = clsname;
for i=1:2:length(varargin)
key = varargin{i};
addprop(self, key);
prop = findprop(self, key);
prop.SetMethod = makefunc(key, varargin{i+1});
end
end
function out = classname(self)
out = self.name_;
end
end
end
function h = makefunc(key, argtype)
h = #newfunc;
function newfunc(obj, val)
obj.(key) = argtype(val);
end
end
With this class I'm defining the set method so that the parameter passed to the attribute is copied to the right type. To see what I mean consider the following usage:
>> p_int = myDynamicClass('Point', 'x', #int8, 'y', #int32);
>> p_int.x = 1000
p_int =
myDynamicClass with properties:
y: []
x: 127
>> class(p_int.x)
ans =
int8
With this we have forced the x attribute to be an integer of 8 bits which can only hold integers from -128 to 127. Also notice how the class of each attribute gives us the intended type.
My experience with Matlab has been so far, that once I create an instance of a class, adding new methods is not possible. That is very cumbersome, because my object may contain a lot of data, which I'll have to re-load everytime that I want to add a new method (because I have to do clear classes).
It's worth noting for present-day readers of this question that this is no longer true. As of MATLAB R2014b MATLAB updates class definitions at the moment you save them, and the behaviour of existing class instances automatically updates accordingly. In the case of adding new methods, this is uncomplicated: the new method simply becomes available to call on class instances even if they were created before the method was added to the class.
The solutions given for choosing set/get methods for dynamic properties still apply.
There are still cases where you might want to add methods to an instance dynamically and the method doesn't constitute a property set/get method. I think the only answer in this case is to assign a function handle as the value to a dynamic property. This doesn't create a bona fide method, but will allow you to call it in the same way you would a method call:
addprop(obj, 'new_method');
obj.new_method = #(varargin) my_method(obj,varargin{:});
Calls to obj.new_method(args) are thus passed to my_method; however this only works with a scalar obj; an array of instances will have separate values for the new_method property so obj.new_method no longer resolves to a single function handle that can be called if obj is an array.