Package: visualapplets
About visualapplets.pyTheBasler AGcompany provides aTCLscripting engine to automatize the creation ofVisualAppletsdesigns (a former Silicon Software GmbH technology), which is a nice and useful feature but not nice enough, in my opinion.The main idea of thevisualapplets.pyproject is to introduce an additional scripting abstraction and to script the creation of TCL scripts via Python.Huh, to script a script? Too much meta? Let's study an example...ExampleIn this example we will implement theReLUoperator, which functionally corresponds toy(x) = max(0, x).Just for practical reasons, we encapsulate the operator logic in aHierarchicalBox. So it can be reused many times in a VisualApplets design. Consequently we also create a class in our Python script, for the same purpose of course.We begin with the first part of the Python scriptexample.py:importvisualappletsasVAclassExample(VA.Module):def__init__(self,parent,name,x,y):# initialize the HierarchicalBox (e.g. super)super().__init__('HierarchicalBox',parent,name,i=1,o=1,x=x,y=y)# create required modules inside the HierarchicalBox (e.g. self)branch=VA.Module('BRANCH',self,'Branch',o=3,x=1,y=1)condition=VA.Module('IS_GreaterThan',self,'Condition',x=2,y=2)value=VA.Module('CONST',self,'Value',x=2,y=3)decision=VA.Module('IF',self,'Decision',x=3,y=1)# link created modules together, from left to rightself('INBOUND')-branchbranch(0)-decision('I')branch(1)-condition-decision('C')branch(2)-value-decision('E')decision-self('OUTBOUND')# for instance, set desired link propertiesbranch('I')['Bit Width']=16# input link of the BRANCHbranch('I')['Arithmetic']='signed'value('O')['Bit Width']=16# output link of the CONSTvalue('O')['Arithmetic']='signed'# (needs to match the input link)# for instance, set desired module propertiescondition['Number']=0# input value thresholdvalue['Value']=0# output value below thresholdNow the second part of our Python script:# dump generated TCL script to a file instead of stdoutVA.printer=VA.FilePrinter('example.tcl')# create a design with an instance of the example moduledesign=VA.Design('mE5-MA-VCLx','Example')example=Example(design,'Example',x=1,y=2)Finally import the generatedexample.tclfile in the VisualApplets IDE or execute something like this in the TCL console:CloseDesign Discard
source "C:/foo/bar/example.tcl"The resulting design should look similar to this one:Obviously there are more possibilities to implement the ReLU function. You can replace the fallback value by theXORresult or also only check the sign bit of the input value. But the preferred way is probably to utilize the built-inClipLowoperator instead... ;-)BasicsWith the help of the previous example imagine now, how custom algorithms could be implemented without a deepTCLknowledge, but of course not without a certain amount ofPythonexperience.There are a few basic concepts to understand how thevisualapplets.pyworks.ModuleAn instance of the Python module actually triggers theCreateModuleTCL command as well forwards the specified parameters as is:Module(operator,parent,name,i,o,x,y)Onlyxandyarguments will be converted from the grid cell index to the absolute coordinates viavisualapplets.gridinstance. So you don't have to mess up with pixels, just place modules discretely in grid cells.Furthermore each module instance provides an access tomodule port descriptor via()accessor andmodule parameter descriptor via[]accessor.Modules with unambiguous assignable output-input port combination can be directly connected without specifying the source and destination port, likeCONST - BRANCH. Reciprocal connectionBRANCH - CONSTis not necessarily unambiguous, since the branch may have multiple outputs, so you have to specify which one.PortA port descriptor has a little magic inside. Conventionally call the module instance to access either input or output port descriptor:module('I')# default input portmodule('I',0)# samemodule(0,'I')# samemodule('O')# default output portmodule('O',0)# samemodule(0,'O')# samemodule('O',1)# second output port of branchmodule('A')# first input of comparatormodule('R')# rest of division outputmodule()# either default I or O port, which is only determinable in connection contextThere are particular operator specific variations like in case ofDIV,MULTorSUB, where the input index begins with1instead of0and has no specific%03dstring format. Such delicacies are specified in the operator port dictionaryvisualapplets.operators. The port descriptor looks up for the matching dictionary entry. If there is no matching entry, it keeps the specified port name string as is. The dictionary lookup is case invariant and partial string matches are possible, e.g. first letter only if a distinct match is possible.LinkCreation of a link by "subtracting" modules or ports triggers theConnectModulesTCL command:foo=Module('CONST',...)bar=Module('BRANCH',...)link=foo-bar# connect foo to barlink=foo-bar('I')# samelink=foo('O')-bar(0)# samelink=bar-foo# connect bar to foolink=bar('O',0)-foo# samelink=bar(0)-foo('I')# samelink=bar(1)-foo# another branch portfoo-bar# just connect and forget the link descriptorIt is not required to "park" the created link in a variable, only if a link parameter needs to be modified. Another possibility to set a link parameter is to set the parameter of the corresponding port descriptor, which is the same thing.ParamDepending on the context, a parameter descriptor triggers eitherSetModuleParamorSetLinkParamTCL command:# module paramsfoo=Module(...)foo['asdf']=42# assign a intfoo['asdf']='hello'# assign a stringfoo['asdf']=[1,2,3]# assign a list of intsfoo['asdf']=('a','b','c')# assign a string tuple# link paramsbar=Module(...)link=foo-barlink['Bit Width']=24# modify link parameterbar('I')['Bit Width']=24# sameLicenseThis Source Code Form is subject to the terms of the Mozilla Public License 2.0. The fileLICENSEcontains a copy of the MPL. Alternatively obtain another one athttps://mozilla.org/MPL/2.0.