system.tag.readAll COUNTIF

Ok, first things first, it's been awhile since I last posted, and it appears that my scripting skills have rusted over time.

I have 450 OPC Tags that are all integers. There are only 12 values that they can have. What I need is the equivalent of excel's COUNTIF function. I have been unsuccessful in using the system.tag.readAll scripting function.

Example of Tag Layout

There are 13 folders in the Curing folder:

Tags-> US9_FIS-> Curing->
0000
0100
...
1200

For 0000, there are 44 INT Tags. For 0100 - 1200 there are 34 INT Tags in each folder:

US9_FIS
      Curing
            0000
                0001_DTCode_Right
                0001_DTCode_Left
                0003_DTCode_Right
                0003_DTCode_Left
                .
                .
                .
                0041_DTCode_Right
                0041_DTCode_Left
            0100
                0101_DTCode_Right
                0101_DTCode_Left
                0103_DTCode_Right
                0103_DTCode_Left
                .
                .
                .
                0133_DTCode_Right
                0133_DTCode_Left
            .
            .
            .
            1200
                1201_DTCode_Right
                1201_DTCode_Left
                1203_DTCode_Right
                1203_DTCode_Left
                .
                .
                .
                1233_DTCode_Right
                1233_DTCode_Left

My idea is this, create 12 Memory tags to hold the count from each type of code that can exist. Then, loop through all the tags with a system.tag.readAll and count while looping through the tags. I also imagine that I would have to loop for each code, so 12 times? Any assistance would be greatly appreciated!!

Thank you all in advance.

I believe you can do this in one loop by using if statements:

code1Count = 0
code2Count = 0
...
code12Count = 0
tags = ["Tags/US9_FIS/Curing/0000/0001_DTCode_Right","Tags/US9_FIS/Curing/0000/0001_DTCode_Right", etc....]
values = system.tag.readAll(tags)
for x in range(len(tags)):
   value = x.value
   if value==#(Put Code one Value here):
      code1Count += 1
  elif value==#(Put Code two Value here):
      code2Count += 1
...
  else code12Count += 1
         
#Update memory tags with count values
system.tag.write("Tags/code1Count",code1Count)
system.tag.write("Tags/code2Count",code2Count)
...
system.tag.write("Tags/code12Count",code12Count)

I hope this helps

1 Like

Along the lines of Brandon’s suggestion, just avoiding the repetitive if statement:

codes = {}
tags = ["Tags/US9_FIS/Curing/0000/0001_DTCode_Right","Tags/US9_FIS/Curing/0000/0001_DTCode_Right", etc....]
values = system.tag.readAll(tags)

for i in range(len(tags)):
	if values[i].value:
		currentCode = tags[i].split('/')[3]
		if codes.get(currentCode) is not None:
			codes[currentCode] += 1
		else:
			codes[currentCode] = 1

Would output a dictionary like this:
{'0000': 1, '0100': 3, '0200': 0} etc

2 Likes

Thank you for the responses. Is there a way build the tag list dynamically without having to list all 450 tags? That was also something that I was trying to avoid.

root = "US9_FIS/Curing"
folders = ["%02d00" % i for i in range(13)]
suffix = "_DTCode_"

tags = []

def getpath(folder, i, suffix):
	return '/'.join([root] + [folder] + ["%s%02d%s%s" % (folder[:2], i, suffix, "Left" if i % 2 else "Right")])

for index, folder in enumerate(folders):
	if not int(folder):
		for i in range(44):
			tags.append(getpath(folder, i, suffix))
	else:
		for i in range(34):
			tags.append(getpath(folder, i, suffix))

for tag in tags:
	print tag
2 Likes

Paul,

Thank you for the great code. I need to modify it slightly.

Instead of returning, for example, the following:

US9_FIS/Curing/0000/0000_DTCode_Right
US9_FIS/Curing/0000/0001_DTCode_Left
US9_FIS/Curing/0000/0002_DTCode_Right
US9_FIS/Curing/0000/0003_DTCode_Left

I want it to return this:

US9_FIS/Curing/0000/0001_DTCode_Right
US9_FIS/Curing/0000/0001_DTCode_Left
US9_FIS/Curing/0000/0003_DTCode_Right
US9_FIS/Curing/0000/0003_DTCode_Left

I am digging into it myself right now and may come up with a solution on my own (which I would prefer), but any help is appreciated.

I hate feeling like a mooch and a HACK at this, but I only had a loose understanding of Python and Javascript when I first did this 9 years ago. I’ve been out of the game too long and no formal education on this stuff! LOL

Thanks again.

To at least point you in the right direction, since my code’s pretty opaque:
The piece you’ll need to modify is the second argument in the string replacement
(folder[:2], i, suffix, "Left" if i % 2 else "Right")])
So, in this case, i, which is just the loop index, needs to be adjusted so that it increases in steps of 2.
I’d recommend looking at the modulo operator that I did to switch between Left and Right; in this case you can use modulo to add/subtract an offset to the loop index and get the return value you want.

1 Like