With the help of @JordanCClark (thanks, didn’t know about zip), I ended up with the below script. It will take a history tag (integer, float, double) and find the difference over hour intervals between a start and end date. Any value over 0 will be counted. You can rollover at any time, although your process may deem it necessary to only rollover if you aren’t running. You can then use this is a bar chart, for example, to show counts per hour over time. If the tag doesn’t exist, it should just return zeros, not throw an error. I tested with some fairly large sets and it seems to work very well.
#Takes an integer or float tag and returns an accumulated value for each hour within the start/end dates
def hourInterval(tagPath, startDate, endDate):
# Parse Start & End Dates - Attempts to parse a string and create a Date
current = start = system.date.parse(startDate,'yyyy-MM-dd HH')
end = system.date.addHours(system.date.parse(endDate,'yyyy-MM-dd HH'), 1)
#Get data from tag history
result = system.tag.queryTagHistory(
paths = [tagPath],
startDate = start,
endDate = end,
aggregationMode = 'MinMax',
ignoreBadQuality = True,
timeout = 10000,
returnSize = 0 #Natural
)
dataHeaders = ['t_stamp', 'value']
data = [[system.date.parse(result.getValueAt(row,0)), result.getValueAt(row,1)] for row in range(result.rowCount)]
if result.rowCount <=0: #if no data, create at least one row
data.append([startDate,0])
dataSet = system.dataset.toDataSet(dataHeaders, data)
# Convert to get a PyDataSet.
pyData = system.dataset.toPyDataSet(dataSet)
# Create a dictionary with all the hourly times as keys
timeDict = {}
while system.date.isBefore(current, end):
timeDict[current] = 0
current = system.date.addHours(current, 1)
# Get first row of the dataset:
if len(pyData) > 0:
date, value = list(pyData[0])
# Set minutes and seconds to zero
date.setSeconds(0)
date.setMinutes(0)
# Iterate through the rest of the rows.
# With a PyDataSet we can use a slice to start at the second row
# With zip, we can now iterate through the sliced dataset and the original at the same time.
for row, prevRow in zip(pyData[1:], pyData):
# Get dates and values for the current and previous rows,
# then set minutes and seconds to zero.
date, value = list(row)
prevDate, prevValue = list(prevRow)
date.setSeconds(0)
date.setMinutes(0)
prevDate.setSeconds(0)
prevDate.setMinutes(0)
# update the current hour with difference.
if value > prevValue:
timeDict[date] += value - prevValue
# if value is lower than the previous value, add the full value.
elif value < prevValue:
timeDict[date] += value
# Create and return a dataset created from the time dictionary.
headers = list(pyData.getColumnNames())
dataOut = [[system.date.format(time, 'MM-dd HH:00'), float(timeDict[time])] for time in sorted(timeDict.keys())]
return system.dataset.toDataSet(headers, dataOut)