Start and End data values

Maybe this will help to clarify what is happening. I’ve got the tables showing the values for the tank volume at start and end dates of the chart, the third table “Tank 1 Volumes” should be showing the difference between the two readings, thus providing the net loss of volume. For some reason the script from @dkhayes117 is always calculating the same value, despite changing the start and stop dates. I think I’m very close to figuring this out, I just don’t know how to read the value of the power table cells into the Starting volume and Ending volume fields. I’ve tried a few different ways, but keep getting errors like:
File “event:propertyChange”, line 8, in
TypeError: can’t convert Dataset [1R ⅹ 2C] to double

I thought the tag value was a double already, from TagHistorian.

Lets try this a little differently. Change the aggregationMode to MinMax. (Assuming your volume measurement is cumulative) This will return two rows where index 1 is your volume measurement. Row 0 is max, and row 1 is min.

history = system.tag.queryTagHistory(paths= [tagPath],startDate=startDate,endDate=endDate,returnSize=1,aggregationMode='MinMax')
startVolume = history.getValueAt(1,1)
endVolume = history.getValueAt(0,1)

event.source.parent.getComponent('Start Volume').value = startVolume
event.source.parent.getComponent('End Volume').value = endVolume

You then can make your volume change label an expression binding subtracting the other two numeric label values. This is unnecessary if you only want the volume change value, but if you want to display the start and stop values too, then use MinMax like I just described.

As far as your error, it is telling you exactly what the problem is. You cannot assign a dataset to a numeric label value. You need to index the value from the dataset, then assign it to the label.

The script maybe running faster than the chart is updating its values. In that case, you should invokeLater the script.

PS: I tested the Range aggregation on my system, and it worked as expected

I think this is what I'm trying to do, but keep getting the error I mentioned above. I'm trying to use: Root Container.Tank 1 Volumes Start.data(0,1) as the value, which I thought would be (row,column) from the table "Tank 1 Volumes Start", I used the properties browser to find it.

I do want to display the Start volume and End volume for the user to see, and for my own learning. Is there anything other than the docs site? Something that can give more beginner-friendly information? I feel like I'm way over my head here.

Post your exact script, and I will help you work it out.

The only other resource for Ignition that might be more introductory is www.inductiveuniversity.com

The IT lords here have broken the videos at inductiveU, but I have read the transcripts on many areas.

This is from the power table "Tank 1 Volumes" in the PropertyChange scripting window:
if event.propertyName == 'startDate':
startDate = event.source.startDate
endDate = event.source.endDate
tagPath= '[default]Work Tank 1/Work Tank 1 Volume Imperial Gallons'
history = system.tag.queryTagHistory(paths=[tagPath],startDate=startDate,endDate=endDate,returnSize=1,aggregationMode='Range')

event.source.parent.getComponent('Tank 1 Volumes').data = history

Sorry, I don't know how to format it to look like code.

This is how
image

if event.propertyName == 'startDate':
    startDate = event.source.startDate
    endDate = event.source.endDate
    tagPath= '[default]Work Tank 1/Work Tank 1 Volume Imperial Gallons'
    history = system.tag.queryTagHistory(paths= [tagPath],startDate=startDate,endDate=endDate,aggregationMode='MinMax')

    'putNumericLabelValuePathHere' = history.getValueAt(1,1)  //something like Root Container.Start Volume.value = 
    'putNumericLabelValuePathHere' = history.getValueAt(0,1)

I really appreciate everyone suffering through this with me!

I’ve tried with a few different aggregation modes, still getting strange results. Currently using this script on the power table:

if event.propertyName == 'startDate':
    startDate = event.source.startDate
    endDate = event.source.endDate
    tagPath= '[default]Work Tank 1/Work Tank 1 Volume Imperial Gallons'
    history = system.tag.queryTagHistory(paths= [tagPath],startDate=startDate,endDate=endDate,aggregationMode='Range')

    event.source.parent.getComponent('Starting Volume').value = history.getValueAt(1,1)
    event.source.parent.getComponent('Ending Volume').value = history.getValueAt(0,1)

I get different values in @dkhayes117 power table compared to when I use a historical tag query for the other power tables above. I don’t know why, since they seem to be using the same variables for start and end dates,

How do I get the value from a cell in the power table into the numerical fields “Starting Volume” and “Ending Volume”? I’ve tried using properties and linking to the table using “Root Container.Tank 1 Volumes Start.data(0,1)” but I get error " The type of the property you chose ( Dataset ) is not assignment-compatible with the type of the property you are binding to ( double )." I thought the data in the dataset WAS a double, since it’s just the same values the tag history is keeping. Doesn’t the (0,1) reference to the cell data, not the whole data set? Or do I need to index the whole dataset and then use the (0,1) to reference within that set? If only tag History was available on the numerical input properties! Or is it, and I just don’t know how?

Ignore the value in the Starting Volume, Ending Volume, and Preservative in Charge, I don’t know why they aren’t zeroed out.

I left out the returnSize=1 part, add that back.

Range aggregation will return the difference between the min and max values over your date range. If your values at start and end are not the min and max values then Range isn’t what you want. You would use tagHistoryQuery twice using LastValue aggregation. For start value, use the startDate for both query start and end dates. For end value, use the endDate for both start and end dates. Assign these values along with the difference between them to your labels from the event handler.

You are better off not using property bindings on the table, do everything from the event handler so everything is in one spot. I would never use an index binding to a table’s dataset, use scripting to get the values you want.

I think this is what I effectively did with the two upper power tables, but configured via Tag History on the data binding. This is where you recommend not using property binding?

Currently have this:

if event.propertyName in ('startDate', 'endDate'):
    startDate = event.source.startDate
    endDate = event.source.endDate
    tagPath= '[default]Work Tank 1/Work Tank 1 Volume Imperial Gallons'
    history = system.tag.queryTagHistory(paths= [tagPath],
    startDate=startDate,
    endDate=startDate,
    returnSize=1,
    aggregationMode='LastValue')

and vice versa for Ending Volume value, but using endDate for both dates

Getting a 0 in the Starting Volume, after deleting the previous value. It won’t let it be left blank, says error setting to NULL.

sidenote: I think I’m starting to get a feel for the scripting syntax and references.

Looking better

if event.propertyName in ('startDate', 'endDate'):
	startDate = event.source.startDate
	endDate = event.source.endDate
	tagPath= '[default]Work Tank 1/Work Tank 1 Volume Imperial Gallons'
    
	startDS = system.tag.queryTagHistory(paths= [tagPath],
    	startDate=startDate,
    	endDate=startDate,
    	returnSize=1,
    	aggregationMode='LastValue')
    	
	endDS = system.tag.queryTagHistory(paths= [tagPath],
   		startDate=endDate,
    	endDate=endDate,
    	returnSize=1,
    	aggregationMode='LastValue')
    	
	startVol = startDS.getValueAt(0,1)
	endVol = endDS.getValueAt(0,1)
	volDiff = endVol - startVol
	
	event.source.parent.getComponent('Starting Volume').value = startVol
	event.source.parent.getComponent('Ending Volume').value = endVol
	event.source.parent.getComponent('Volume Diff').value = volDiff
2 Likes

Just zeros, everywhere. I even tried print startVol just to see if it’s working, but nothing, not even error.

I put this script on the powertable as before, maybe something is overwriting the value?

event.source.parent.getComponent('Starting Volume').value = startVol
event.source.parent.getComponent('Ending Volume').value = endVol
event.source.parent.getComponent('Volume Diff').value = volDiff

Success! Can’t thank everyone enough, especially @dkhayes117

I put this on the PropertyChange of the easy chart, moved a few things around internally. Now it’s getting the values and differencing them! Now to add a manual adjustment input…

if event.propertyName in ('startDate', 'endDate'):
	startDate = event.source.startDate
	endDate = event.source.endDate
	adjVol = event.source.parent.getComponent('Manual Adjustment Input').floatValue
	tagPath= '[default]Work Tank 1/Work Tank 1 Volume Imperial Gallons'
    
	startDS = system.tag.queryTagHistory(paths= [tagPath],
    	startDate=startDate,
    	endDate=startDate,
    	returnSize=1,
    	aggregationMode='LastValue')

	endDS = system.tag.queryTagHistory(paths= [tagPath],
   		startDate=endDate,
    	endDate=endDate,
    	returnSize=1,
    	aggregationMode='LastValue')
    	
    	startVol = startDS.getValueAt(0,1)
    	endVol = endDS.getValueAt(0,1)
    	diffVol = startVol - endVol - adjVol
    	
    	event.source.parent.getComponent('Starting Volume').value = startVol
    	event.source.parent.getComponent('Ending Volume').value = endVol
    	event.source.parent.getComponent('Differential Volume').value = diffVol

I’d like to make it update the diffVol on keypressed (or maybe mouse moved?), but not sure about passing values from one scripted component to another; as long as I use the same names, it should work?

2 Likes

You could right-click on your easy chart, or wherever your current script is living, and add a custom property. Then bind that custom property, adjustment, to the adjusted volume value property. Then simply change your first line to this

if event.propertyName in ('startDate', 'endDate', 'adjustment'):
    do stuff

EDIT:
Or if you don’t want to run all your code again you can simply write another code block under the first one

if event.propertyName in ('startDate', 'endDate'):
    do stuff
if event.propertyName == 'adjustment':
    do less stuff
1 Like

The problem is not as simple as it sounds. I had same type of issue, I just want the value at the time I give it. I had to work around it by getting the value before and after the desired time, and interpolating, unless Interpolation mode =3 (for Ignition 7.9) then you can use first value returned.
in Ignition 8+ they changed the interpolation mode name to something, and instead of an integer, they gave the mode as a name, so code needs to change.

in 7.9 here is how I got the imode value before running code below:
imode = system.tag.read(atag+".InterpolationMode").getValue()

basically I used desired time as enddate, and (desired time - 50ms) for the start date, and then ran this code which returns the value as yval Preformatted text:

	data=system.tag.queryTagHistory(tagpaths, startDate=txxb, endDate=txx, returnSize=-1, noInterpolation=-1, aggregationMode="LastValue", returnFormat='Wide',includeBoundingValues=-1)
	np=data.getRowCount()
	nc=data.getColumnCount()
	#print tagpaths
	if np != 0:
		if (np >1):

			ygy1=data.getValueAt(0,1)
			yt1 =data.getValueAt(0,0)
			ygy2=data.getValueAt(1,1)
			yt2 =data.getValueAt(1,0)

			yt1n = yt1.getTime()
			yt2n = yt2.getTime()
			tdiff = yt2n - yt1n
				
			#print tdiff,txx
		
		
#.interpolate the value at the cursor.
			if (imode==3): 
				yval= ygy1 + ((ygy2 - ygy1) * (txx-yt1n)/ tdiff)
			else: 
				yval=ygy1
#		yval=ygy1
		else:
			ygy1=data.getValueAt(0,1)
			yt1 =data.getValueAt(0,0)
			yval=ygy1

The problem is not as simple as it sounds. I had same type of issue, I just want the value at the time I give it. I had to work around it by getting the value before and after the desired time, and interpolating, unless Interpolation mode =3 (for Ignition 7.9) then you can use first value returned.

This is what I ran into as well, I figured with how easy the chart was to setup, and then the relative ease of getting the value at start and end date, it should be easy to use those values in a calculation, but not so! As you see above, it took quite a bit of scripting to be able to use those values.

I'm not sure if this was introduced with a recent Ignition update or I missed it during role-out. Often the users don't tell me something isn't working. I get an error regarding the scripting:

Traceback (most recent call last):
File "event:propertyChange", line 22, in
TypeError: unsupported operand type(s) for -: 'NoneType' and 'NoneType'

Line 22 is: diffVol = startVol - endVol - adjVol

I moved the terms around and commented them out, I think I've got it figured out why it's an error, but not sure about a solution. I think it's trying to subtract two decimal values (I'm unsure of the type, is it the same as the original historical tag?) and a float value. The startVol and endVol are pulled from the easy chart start and end dates (a query to the database) and the adjVol is a user-entered value from a numeric text field (is this the correct type?). I think the script is okay with the user-entered value since it is a float but is there a way to change the other two values to be floating type?

Just wrap numerical values in float() to cast them to a floating type, but that isn't the issue here. NoneType means null, so for some reason, at least two of the three subtracted values are not being returned.

Could it be because the endVol is part of a timespan on the easychart which has no value? If so, how do I set the initial state of the easychart to not include that time? When I include the empty data time after the initial error, the value in the endVol is 0, no errors or anything. I'm not sure if it's relevant, but there's two easycharts, one on each tab, and I don't get the error in the script on the 2nd tab.