Masks and strings in the Engee Function
In Engee, you can add a simple user interface to a block. This is called block masking. Masks can be used to hide the internal structure of the unit from the user. This is a great technique, and let's add a mask to the Engee Function block from last post.
The EF_pdist2 function that we used has an optional parameter, the calculation mode (metric). During the project, we will give the user the opportunity to control it through a mask.
include("PDIST2.jl");
Let's remember what the module code looks like.:
;cat PDIST2.jl
How do I pass a string from a mask to an Engee Function?
Before masking the Engee Function, it is necessary to consider a functional limitation - the Engee Function cannot work with type parameters. String. But the calculation method is set by a string. Therefore, we need to encode the selected method with a certain number, pass this number as a parameter to the Engee Function, and then decode it. In other words, the mask will need not one parameter, but two. Then you can implement such a scheme:
We will decode the calculation mode using a dictionary, since the Dict data type implements a collection of key-value pairs. In this case, the key can be any base type. Therefore, it is possible to make even such a dictionary.:
mode_dict_t = Dict(1=>"euclidean",2=>"squaredeuclidean",3=>"manhattan",4=>"cosine")
It can be seen that the key here is an integer, and the value is a string. This allows us to do the following:
EF_mode = PDIST2.mode_dict_t[1]
Now let's take a look at the code of the Engee Function block methods.:
include("/user/start/examples/base_simulation/advanced_block_masking/PDIST2.jl")
mutable struct Block <: AbstractCausalComponent
cache::Matrix{Float64};
modeC::Int64
function Block()
c = zeros(Float64,INPUT_SIGNAL_ATTRIBUTES[1].dimensions);
info("Allocated $(Base.summarysize(c)) bytes for pdist2")
info("Selected $(PDIST2.mode_dict_t[mode])")
new(c,mode)
end
end
function (c::Block)(t::Real, in1, in2)
try
c.cache = PDIST2.EF_pdist2(in1,in2;metric=PDIST2.mode_dict_t[c.modeC]);
catch
error("Matrix Dimensions should be equal!")
stop_simulation()
end
return c.cache
end
modeC is a parameter that takes the value of a numeric variable from a mask (see ). Thus, we can pass the calculation method to our PDIST2 function as
PDIST2.mode_dict_t[c.modeC]
And we will get the number by calling back the "real" parameter from the drop-down list.:
if mask.parameters.mask_mode.value == "euclidean"
mask.parameters.mask_mode_int.value = 1;
elseif mask.parameters.mask_mode.value == "squaredeuclidean"
mask.parameters.mask_mode_int.value = 2;
elseif mask.parameters.mask_mode.value == "manhattan"
mask.parameters.mask_mode_int.value = 3;
elseif mask.parameters.mask_mode.value == "cosine"
mask.parameters.mask_mode_int.value = 4;
end
So the mask will look like this:
Note that the mask_mode_int parameter must be computable. And it's hidden because we don't want to let the user break anything.
Finally, we will open and run the final model in all modes.:
demoroot = @__DIR__
mdl = engee.open(joinpath(demoroot,"EF_DF.engee"))
for k in keys(PDIST2.mode_dict_t)
println("Запускаем модель с режимом $(PDIST2.mode_dict_t[k])")
engee.set_param!("EF_DF/PDIST2", "mask_mode"=>PDIST2.mode_dict_t[k])
engee.run(mdl;verbose=true);
end
Conclusions
During the project, we learned how to drop string parameters into the Engee Function, and also used dictionaries in a standard, albeit unobvious way.