Hello everyone!
I have some bool tags:
tag1
, tag2
and tag3
And an result tag: result
I have some combinations that generates a different input depending on the tags. For example:
tag1 |
tag2 |
tag3 |
result |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
- |
0 |
1 |
1 |
- |
1 |
0 |
0 |
4 |
1 |
0 |
1 |
7 |
1 |
1 |
0 |
8 |
1 |
1 |
1 |
99 |
How could I make this transformation? I was thinking of using the Expression Tag
but it's a bit of a nightmare with the expression language.
Any idea of how could I do this more easily?
Any help is appreciated.
Note: In this example tag1, tag2 and tag3 are bool but could be int or float too.
Edit: Not looking too much into it the most viable way i'm thinking is using runScript() from the expression language.
One person in another forum suggested using a dictionary:
{
"0":{
"0":{
"0":0,
"1":0
},
"1":{
"0":"-",
"1":"-"
}
},
"1":{
"0":{
"0":4,
"1":7
},
"1":{
"0":8,
"1":99
}
}
}
But for some reason I really hate this approach even if it's a good idea.
Make the result tag an expression binding and use the following expression:
case(
binEnc(
{[.]Tag3}, // +1 LSB
{[.]Tag2}, // +2
{[.]Tag1} // +4 MSB
),
0, 0,
1, 0,
4, 4,
5, 7,
6, 8,
7, 99,
null
)
... but it's a bit of a nightmare with the expression language.
Nah!
1 Like
Wow, didn't knew about binEnc.
However, when I have a value that is not binary and is an Integer
I will have to transform to bits and encode thoes too.
Thanks a lot @Transistor !
If it's already an integer then the bits are already encoded.
If you have bits and an integer then just shift the integer bits left by multiplication:
case(
binEnc(
{[.]Tag3}, // +1 LSB
{[.]Tag2}, // +2
{[.]Tag1} // +4 MSB
)
+ {[.]IntTag} * 8, // Shift left by 3 bits.
1 Like
I know you said you hated this approach, but you could do something like below:
resultTable = {
"0#0#0": 0,
"0#0#1": 0,
"0#1#0": "-",
..........
"1#1#1": 99
}
Instead of having nested dictionaries, you could just join the values of the 3 tags with the character # for instance (or any other character really, could even be a comma) and then you could just access the key that has the same value as the joined string.
key = "#".join([str(valTag1), str(valTag2), str(valTag3)])
return resultTable[key]
I personally think this is more readable and easier to add new entries but again just my opinion...
This would work with floats and integers too.
1 Like
To explain your use of dictionaries fully you'd need to address where the script would go and what would trigger the update when one of the dependencies changes.
The expression does this automatically and doesn't require loading the Jython interpreter every time it's triggered and the expression is in the actual tag. Note that you can't use Perspective's Expression Structure binding and transforms on an expression tag.
1 Like
Combine both approaches:
case(
stringFormat("%d.%d.%d", {Tag1}, {Tag2}, {Tag3}),
"0.0.0", 0
"1.1.1", 99
...
// fallback
)
Fast(ish), because expressions, and more readable/maintainable.
7 Likes
Your soultion is the one.
However, I think you mean stringFormat()
instead of numberFormat()
.
Could be?
case(
stringFormat(
"%s.%s",
{[.]tag},
{[.]tag}
),
"1.1", 97,
"5.5", 98,
"2.2", 14,
"3.3", 89,
"4.4", 88,
99 // fallback
)
1 Like
Yes, you're right; numberFormat
is limited to converting a single number to a string, stringFormat
is what you want here to concatenate + format in one operation.
2 Likes
[Posted a reference to this thread in this thread!]