Use Logical as reference

Hello,

I like to create logic as this

if(1=1,True,False).

But I want logical = to be as reference like this:

if(1({Root Container.Group.1_S.Current_Logic})1,True,False)

{Root Container.Group.1_S.Current_Logic} can be any of the standard Logical (>,<,>=,<= etc)

Best regards
Pawel

Can’t do it this way. While I have no idea how expressions are parsed and interpreted, I highly doubt you can use an identifier as an operator.

What exactly are you trying to do ?

you could create expression functions in a module, not an easy task though.

you are better of using a case function if the options are defined

Thanks for your feedback.
I am trying to replace this expression:

if(lookup({Root Container.Group.1_S.Current_DB},2,-1)=-1,0,
if({Root Container.Group.1_S.Current_Logic}='=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='<=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)<=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='>=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)>=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='!=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)!=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='>',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)>lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='<',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)<lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
0)))))))

With something much simpler I will need to bind this expression across 155 components and unfortunately each of this expression will need to be modified.

I am working on MDI board called SQDIP (Safety, Quality, Delivery etc) then each letter contain 31 days.
image
each day is representing by target and current value, which can be any value coming from DB.
So, I need to use Logical to determinate colour for each day, red, green white. So the above expression is required to give me different status.

I can do this by copying above expression and modify for each letter and day but it will be very long process.

So I tried to figured out if Logical can be dynamic.

Create a custom property on each block that looks up the value and returns an integer value representing the ‘status’ of what you are looking for.
Then do custom styling on each that uses that integer to color the block it is on.

This is what above logic represents on a custom property for each letter/day.
0 = white
1 = green
2 = red

My problem is to not need to update each letter with this expression and use shorter version of this expression by dynamically get logical from custom parameter.

I think this is a very valid use case for using runScript because this

if(lookup({Root Container.Group.1_S.Current_DB},2,-1)=-1,0,
if({Root Container.Group.1_S.Current_Logic}='=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='<=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)<=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='>=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)>=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='!=',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)!=lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='>',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)>lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
if({Root Container.Group.1_S.Current_Logic}='<',if(lookup({Root Container.Group.1_S.Current_Target_DB},2,0)<lookup({Root Container.Group.1_S.Current_DB},2,0),1,2),
0)))))))

I would not want to maintain especially if it might get larger. Write a python function with the logic and call it on some custom property - runScript - Ignition User Manual 8.0 - Ignition Documentation

Holy Ninja Turtles that's an ugly expression !
Fun fact: In French, there's a tree that's called if. So you literally have forests of ifs.

First, instead of copy/pasting things over hundreds of components, make a template.
If you're on perspective, just create a view with your component, and repeat that view. That way, you don't have to change all of them when you want to modify something.

Then, a switch/case expression is usually preferable to a bunch of ifs.

And finally:

I feel like there ought to be a better way to do this, but we'll need more details about the workings of your thing to help you find it.
ie: what determines the operator ? (this: {Root Container.Group.1_S.Current_Logic}. Where does it come from ?)

At the very least (I’m still convinced there’s a better way), you could use something of this sort:

Which I believe does the same thing, but slightly more readable / maintainable.

More details = better solutions, though.

1 Like

You really, really don’t want to do this. script your query and modify the dataset.
EDIT: The upshot of doing this is that you can reduce your expressions to lookups.

3 Likes

An example, now that I’m between meetings:

##########################################################
# Sample Data
headers = ['day', 'Safety', 'Quality Defects', 'Deliverables']
data = [[1,  0,   0, 100],
        [2,  1,   0,  75],
        [3, 10,   0,  95],
        [4,  0,  10,  89],
        [5,  0,   0,  90]
       ]
###########################################################

def compare(x, y, compareType):
	'''
	Function to return True/False for a given comparison type
	Leverages Python's cmp() function.
	'''
	compareDict = {'==' : [0],
	               '!=' : [-1, 1],
	               '>'  : [1],
	               '<'  : [-1],
	               '>=' : [0, 1],
	               '<=' : [-1, 0]
	              }

	return cmp(x, y) in compareDict[compareType]

# Simulate query form sample data
ds = system.dataset.toPyDataSet(system.dataset.toDataSet(headers, data))

# Get column names from the PyDataSet 
colNames = list(ds.getColumnNames())
# Generate color column names
colorColNames = ['{} Color'.format(col) for col in colNames[1:]]

# Initialize dictionary of comparison thresholds and types.
compareData = {'Safety'        : {'value': 0, 'compareType': '=='},
              'Quality Defects': {'value': 0, 'compareType': '<='},
              'Deliverables'   : {'value': 90, 'compareType': '>='}
             }

# Create processed dataset, adding comparison colors
dataOut = []
for row in ds:
	newRow = list(row)
	for col in colNames[1:]:
		if compare(row[col], compareData[col]['value'], compareData[col]['compareType']):
			newRow.append('Green')
		else:
			newRow.append('Red')
	dataOut.append(newRow)

datasetOut = system.dataset.toDataSet(colNames+colorColNames, dataOut)

Resultant dataset:

row | day | Safety | Quality Defects | Deliverables | Safety Color | Quality Defects Color | Deliverables Color
---------------------------------------------------------------------------------------------------------------
0   | 1   | 0      | 0               | 100          | Green        | Green                 | Green             
1   | 2   | 1      | 0               | 75           | Red          | Green                 | Red               
2   | 3   | 10     | 0               | 95           | Red          | Green                 | Green             
3   | 4   | 0      | 10              | 89           | Green        | Red                   | Red               
4   | 5   | 0      | 0               | 90           | Green        | Green                 | Green             
4 Likes

There’s probably also an approach using the operator module, but I’m too lazy to do the legwork :slight_smile:

1 Like

I guess he could replace the operator symbols in his lookup map by their representations ("eq" for "=", etc.), then do something like

import operator

op = get_the_operator_from_the_lookup_map()
op = getattr(operator, op)
return op(a, b)

or if you like onliners

return getattr(operator, get_operator_from_table)(a, b)