Altering value(s) within pydataset

I have created a pydataset by collecting information from a number of UDT tags I have set up. The information is coming in correctly. What I want to do for a few of the items is to say if one element of the list of lists says something like 1000 I want to actually replace it with a value of 0. There is a reason I have it set to 1000 but whats the best way to go through my pydataset and loop through and say for every list, go to element 5 and if that value is 1000 go ahead and replace it with a 0. There is another 1 or two elements I would have to do this with and I know you can't edit a pydataset. You can only alter and make a new one which would mean I would have to create 2 or 3 new ones based on the original. I am converting this to a dataset so I can make an html document out of it so maybe its better to convert to a dataset then work with it that way?

Here is a screenshot of the output console I have with it showing the pydataset values. Had to break it into two so its legible.

image

Take care of it just before you append the row.

if AIrow[5] == 1000:
    AIrow[5] = 0
2 Likes

Use a pyDataSet. Those are not immutable. nevermind.

Also, I'd try and make just one call to system.tag.browse. You can pass it a filter to make it target your UDT specifically, and do it recursively:

filters = {
    'tagType': "UdtInstance",
    'typeId': "your_udt_name",
    'recursive': True
}
indices = [2, 7, 12, 11, 10, 0, 1]
AIrows = [
    [
        AIudt[i].value for i in indices
    ] for AIudt in system.tag.browse("starting_path", filters)
]

Note at this point this is not a dataset. You can modify it as you like.
I'll try and make a script for you when I have some more time. Now is a good time to list constraints and what not.

2 Likes

Perhaps I'm missing something:

2 Likes

Another option: Ignition Extensions adds system.dataset.map.

Huh. I guess they are... No idea why I thought they were not.

Worked perfect, thanks!

In the output console it worked perfect. I put this same logic in a script and added a tag write command to transfer the dataset to a dataset tag. I am getting the following error:

	AIpath = "[PLC]AnalogInputs"
	AIresults = system.tag.browse(AIpath)
		
	AIudtPaths = [result['fullPath'] for result in AIresults]
		
	AIheaders = ["Analog Input","Value","Units","Totalizer", "Total Units","Alarm High Setpoint", "Alarm Low Setpoint"]
	AIrows = []
		
	for AIudtPath in AIudtPaths:
		AIudt = system.tag.browse(AIudtPath)
		AIrow = [AIudt[2]['value'].value, AIudt[7]['value'].value,
			AIudt[12]['value'].value, AIudt[11]['value'].value,
			AIudt[10]['value'].value, AIudt[0]['value'].value,
			AIudt[1]['value'].value]
		if AIrow[4] == u'':
			AIrow[4] = 'null'
		if AIrow[5] == 1000.0:
			AIrow[5] = 0
		if AIrow[6] == -1000.0:
			AIrow[6] = 0
		AIrows.append(AIrow)
		
	AIdataset = system.dataset.toDataSet(AIheaders, AIrows)
				
	AIstatus = '[PLC]AnalogInStatus'
	system.tag.writeBlocking(AIstatus, AIdataset)	

AIdataset is simply a dataset tag so I can make sure the correct data is being populated

Line 77 is where I set to AIdataset to the dataset with AIheaders and AIrows

If I comment out the AIrow[5] logic to change 1000 to 0 it works fine. These two lines are not allowing it to work

Click on the plus sign to expand that error, and copy the whole thing here to provide context to the error. Specifically the caused by statement

com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 2, in runAction File "", line 75, in CreateSendStatusFiles TypeError: Unable to convert row 2, column 5 to type class java.lang.Integer

at org.python.core.Py.TypeError(Py.java:236)

at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities.toDataSet(DatasetUtilities.java:623)

at jdk.internal.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:190)

at org.python.core.PyReflectedFunction.call(PyReflectedFunction.java:208)

at org.python.core.PyObject.call(PyObject.java:477)

at org.python.core.PyObject.call(PyObject.java:481)

at org.python.pycode._pyx26.CreateSendStatusFiles$1(:78)

at org.python.pycode._pyx26.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyBaseCode.call(PyBaseCode.java:119)

at org.python.core.PyFunction.call(PyFunction.java:406)

at org.python.pycode._pyx25.runAction$1(:2)

at org.python.pycode._pyx25.call_function()

at org.python.core.PyTableCode.call(PyTableCode.java:173)

at org.python.core.PyBaseCode.call(PyBaseCode.java:306)

at org.python.core.PyFunction.function___call__(PyFunction.java:474)

at org.python.core.PyFunction.call(PyFunction.java:469)

at org.python.core.PyFunction.call(PyFunction.java:464)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:843)

at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:825)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:828)

at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:1006)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:893)

at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:147)

at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:74)

at com.inductiveautomation.perspective.gateway.action.ActionDecorator.runAction(ActionDecorator.java:18)

at com.inductiveautomation.perspective.gateway.action.SecuredAction.runAction(SecuredAction.java:44)

at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)

at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)

at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)

at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)

at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)

at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)

at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:58)

at java.base/java.lang.Thread.run(Unknown Source)

Caused by: org.python.core.PyException: TypeError: Unable to convert row 2, column 5 to type class java.lang.Integer

It appears that in some cases, AIrow[5] is not equal to 1000, and it isn't a value that can be converted to an Integer. What is the value of Alrow[5] in row 2?

Looks like they are all numbers to me

image

Is it the Integer 1000 or the Float 1000.0?

The comparison would work either way, but the type conversion would not be allowed because you could be truncating data.

Make sure that the types match everywhere.

1 Like

that was it. once I changed the alarm high setpoint UDT value to integer it worked!