How to get area under curve

I have a tag power_kW where I am historizing.

I want to get Energy between time interval.

So I did tag query power_kW for a given time interval.

If I plot it on a chart, The energy should be the area beneath the power_kW curve.

Is there a function to get the Area below the curve?

Divide the sum of power by the number of samples per hour.
So if you have an aggregation interval of 5, energy = sum(power) / (60 / 5)

A quick way to get the sum of a column from a dataset is by doing the following:

def sum_col(dataset, col_name):
	col_data = ds.getColumnAsList(ds.getColumnIndex(col_name))
	return sum(col_data)

ds = system.dataset.toDataSet(['test'],[[1],[1],[1]])
sum_col(ds, 'test')

Replace 'ds' with whatever dataset you have and 'test' with the column name you want.

If you are doing energy metering then I recommend recording the kWh rather than kW and doing it on a periodic schedule to a dedicated database. It makes energy calculations over any time period very easy. Historian is not good for this sort of job.

Integrate :wink:

6 Likes

This post reviews the operation, scroll down to the bottom for the proper download.

You are right. write to database and reset value in regular interval..?

I was thinking of alternative to this, where user can enter time range of any granularity.

You said it. Was wondering if there was a built-in function for it. Or a kind person has an elegant code, I can start with..

Python numpy should have something like that.

Dude, really? :wink: Around post 5 in this thread...

No, never reset. Use it like your utility company does and just record the kWh reading and t_stamp. Then you can calculate the energy used in any time period by subtracting the first reading from the last.

To generate data for a chart you would need the difference between successive kWh readings.

One other big benefit of this method is that, should the logging fail for a period of time, you can still calculate the average energy use through the data gap. With kW logging you can't.

1 Like

My head hurts, lets take a step back.

Suppose I have a tag, energy_kWH, which is accumulates indefinitely.

Goal is to record the daily energy usage.

Every midnight, I run my code, read energy, and set timestamp and write it on database.

so I have the below on database:

midnight1, energyNow - energy0
midnight2, energyNow - energy1
missed(code did not run)
midnight4, energy is ??

Compare with reset:
midnight1, energyNow (then reset)
midnight2, energyNow (then reset)
missed(code did not run)
midnight4, energyNow (wrong measurements)

Option 3:
Historized power_kW,
get the curve from yesterdayMidnight to today's midnight, energy is the area of curve.

How did option 1 became the best option?

Option 4: Historized energy_kWH
get Energy at yesterday midnight
get Energy at today's midnight
energy today = the difference

Because you can never lose any information. With any reset operation, there is always a tiny interval where an increment can be lost.

Also, you don't have to record just at midnight. You can record on the hour, every hour. Or every minute on the minute. Or every five minutes. Whatever granularity you choose, and never losing any information. For any longer period, the energy is simply the first recorded value after the period minus the first recorded value of the period. Trivial in any database.

When recording more often, you minimize the disruption of downtime, as the energy is simply accounted to the next recording, not lost.

2 Likes

For multiple meters I'd recommend a table structure like this:

  • t_stamp
  • meterId
  • kwh_reading
  • kvar_reading

Everything else can be calculated by SQL or script.

@pturmel, I'm interested in what you'd recommend for t_stamp values. Would you round down to the nearest second or minute to make the queries easier to catch the boundary records?

Shouldn't be necessary when using properly rounded-down timestamp parameters in the WHERE clause.

It is important that the actual recording be fresh data from the source OPC item, not from a subscribed tag. That is, transaction groups should be configured to OPC Read mode, and scripted inserts should use system.opc.readValues().

2 Likes

But this is what historian does, isn't it?
Then we only need to enable historian for this tag.
(not to stir, but looking for best implementation)

And do query history on this tag on using single time instance.
"What is the Energy yesterday Midnight"
"What is the Energy Today Midnight"
Subtract them.

Main goal really,
I wanted to save in database, discretely because I wanted to show on bar graph Energy Usage Per Day.

No, the historian won't save on even intervals like a scheduled transaction group or a scripted operation in a scheduled event.

Thank you.

I am happy with the below now:
I will historized Energy Tag. Make two queries on it and store the difference in database for reporting.
Its not perfect but should solve most of the problem (missing data, miss "writing to database" code)
This will return 1 value (Maximum within 60sec).

dsEnergy_kWh = system.tag.queryTagHistory(
	paths, 
	startDate=todayMidnight,
	aggregationMode="Maximum",  
	returnSize = 1, 
	rangeSeconds=60)

#return one line:
#[Tue Sep 10 00:00:00 CDT 2024, 316.96161602693377]