Script Averaging calculations Part 2

hi, You all got me going with this script for an average of a three hour block of time:

how difficult would it be to get that to loop through the previous three days? So I can get the average of the previous three days between 0300 and 0600.
I made three of these scripts, one for each of the days, and then averaged those results but maybe I can do it in once shot?

I know there is a looping function but it’s beyond me. I wish I could learn to script but I just can’t seem to speak that language…

Thanks

now = system.date.now()
previousDay = system.date.addDays(now, -1)
time_3am_previous_day = system.date.setTime(previousDay, 3, 0, 0)
startDate = time_3am_previous_day
endDate = system.date.addHours(startDate, 3)

data = system.tag.queryTagCalculations(
paths=['[default]ST25/_25_FI_110X_Total'],
calculations=['Average'],
startDate=startDate,
endDate=endDate

)
return data.getValueAt(0,1)

Are you looking for a single value that's the average of the 3 days? Or are you looking for an average value for each of the prior 3 days?

A single value for the average of the previous three days.

But it isn't just a single value, really.

The way I understand this, is you are looking for the average of the average for each of the last three days during a 3 hour block on each day. Is that correct?

I believe this will do the trick. I added in some extra variables to make tweaking a little simpler

starthr = 3
hrstospan = 3
daystoget = 3
today = system.date.now()

avgSum=0

for day in range(1,daystoget+1):
	startDate = system.date.addDays(today, -day)
	startDT = system.date.setTime(startDate, starthr, 0, 0)
	endDT = system.date.addHours(startDT, hrstospan)
	
	data = system.tag.queryTagCalculations(
			paths=['[default]ST25/_25_FI_110X_Total'],
			calculations=['Average'],
			startDate=startDT,
			endDate=endDT
			)
	avgSum += data.getValueAt(0,1)
	
return avgSum/daystoget
	
2 Likes

that was how I hacked it together. I’m not sure mathematically, out of the bounds of my knowledge, if there would be a difference in an average of three averages or the average of all the values from that the 3day/3hour timer period. either way would work for me I think

Ok, a quick internet search says that the average of the averages and the average of all the raw datapoints will be the same if the sample sizes are all the same. In my case they should be so either way would work

Thanks! I think it’s close, but I get different results from my other averages. If I switch the command to system.tag.queryTagHistory should the For process still work? I only get 1 days worth of data when I do that.

You'll need to figure out the math. But you should be able to use the same basic routine with whatever method you use for calculating the average.

You are manually querying a database. Does that mean you do not have tag historian?

You could start by editing the function to take a date parameter as an input (default none uses system.date.now() ) and use that date as your “now” in the script. Then just call the same function 3 times for the last 3 days and compute the average in the script.

def averageWindow(dateStart = none, span = 3)
	if dateStart is none:
		now = system.date.now()
	else:
		now = dateStart
	previousDay = system.date.addDays(now, -1)
	time_3am_previous_day = system.date.setTime(previousDay, span, 0, 0)
	startDate = time_3am_previous_day
	endDate = system.date.addHours(startDate, 3)

	data = system.tag.queryTagCalculations(
	paths=['[default]ST25/_25_FI_110X_Total'],
	calculations=['Average'],
	startDate=startDate,
	endDate=endDate

	return data.getValueAt(0,1)
#range could be 0-2 depending on when this runs
avgs = [ averageWindow(system.date.addDays(system.date.now(), -1*day)) for day in range(1,3) ]

avg = sum(avgs)/len(avgs)

Can also pass the path in and make this script much more useful

You might want to cast one of the operands to float if the sum is not already one.

I do have the tags in historian; I think I went this way because I didn’t understand what I was doing. How does having a tag history change the approach?

No need to manually query at that point. Use a tag history binding with the selected date range and select average as the aggregation mode.

oh, that looks easier. any thoughts on how to deal with the three day, three hour time block? I can’t really do that in one tag history query can I?

Use custom properties to hold the “selected” dates and use expressions to determine start and end. Bind the custom props to the date inputs in the tag history binding:

(use average instead of closest value)

Thanks, but you’re going to need to back up a step, where are you in that screen? custom property to what?

perspective…

Please update the title. The process will be much the same.

Create 4 custom properties on the view (start, end, data, avg).

start:

dateArithmetic(now(),-3,"day")

end:

now()

data:

tag history binding for your tag using the start and end date specified

avg (pseudocode):

mean({data},1)

You may want to change the argument for now() if you don’t want it updating so often. Or use a script when the view opens to set start and end instead of using a binding. If you’re swapping between hours/days you’ll need some sort of additional logic. If you’re displaying both you can duplicate the process for the other range(s).

Gotcha, I understand. I’m kind of back to where I started but not needing the scripting I don’t really understand.

I don’t see how to edit the title in the forum…

There's a pencil that will appear if you hover over the title. I added the perspective tag for you.

Add 3 (we can use a transform since this is perspective so that removes a step, no need for the “data” value) custom values in the custom props section on the right.

Bind to start and end as specified above.

Fill out tag history binding and add transform for the avg prop binding: