Ignition reporting Script: PyFloat cannot be cast to org.python.core.PySequence

Hello everyone. As you can see from the title I’m having an issue with being unable to cast my data as I attempt to create a new dataset from some data that I modify from an existing dataset.

Below is my code, it’s all fairly shortly.

data_dump = data['part_count'].getCoreResults()
	
rows = data_dump.rowCount
		
adjusted_header = ['total', 'late', 'on_time']
adjusted_data = [0, 0, 0]	
for row in range(rows):
	id_c = data_dump.getValueAt(row, 'id_count')
	total = data_dump.getValueAt(row, 'total')
	late = data_dump.getValueAt(row, 'late')
	on_time = data_dump.getValueAt(row, 'on_time')
	if id_c != 1:
		adjusted_data[0] += total / id_c
		adjusted_data[1] += late / id_c
		adjusted_data[2] += on_time / id_c
	else:
		adjusted_data[0] += total
		adjusted_data[1] += late
		adjusted_data[2] += on_time
		
		
adjusted_dataset = system.dataset.toDataSet(adjusted_header, adjusted_data)
	data['Accurate Counts'] = adjusted_dataset

and my error is the following:

WARN: Error invoking script.Traceback (most recent call last):
  File "<function:updateData>", line 28, in updateData
	at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities.toDataSet(DatasetUtilities.java:317)

	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

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


java.lang.ClassCastException: java.lang.ClassCastException: org.python.core.PyFloat cannot be cast to org.python.core.PySequence

Any help or insight at all would be greatly appreciated. I had assumed that scripting would lead to some easier data modification than attempting to utilize an SQL query to do it, but this is not an error I ever expected to run into.

Thank you!

I’m not sure why you’re getting that error, but your definitely building the dataset incorrectly. You would need to do something like this:

data_dump = data['part_count'].getCoreResults()
	
rows = data_dump.rowCount
		
adjusted_header = ['total', 'late', 'on_time']
adjusted_data = []	
for row in range(rows):
	newRow = []
	id_c = data_dump.getValueAt(row, 'id_count')
	total = data_dump.getValueAt(row, 'total')
	late = data_dump.getValueAt(row, 'late')
	on_time = data_dump.getValueAt(row, 'on_time')
	if id_c != 1:
		newRow.append(total / id_c)
		newRow.append(late / id_c)
		newRow.append(on_time / id_c)
	else:
		newRow.append(total)
		newRow.append(late)
		newRow.append(on_time)
	adjusted_data.append(newRow)
		
		
adjusted_dataset = system.dataset.toDataSet(adjusted_header, adjusted_data)
	data['Accurate Counts'] = adjusted_dataset

Hello Duffanator,

That same method for building a dataset that you recommended to me is something I’ve already done and am doing in other parts of my program, the only difference here is that my goal is it to cut the original dataset, which may have multiple rows, which it should not, down to 1 row that has the totals for all the rows together.

I’m sure there is more manipulation I can do to get it down to that one row that I’m aiming for, but I’ll try this adjustment first to see if the bug goes away in general.

Thank you!

I figured out the issue. The problem was with this line:

It didn't want to cast those from floats/ints to a sequence.

I also determined that an easier way to do this than what I was doing before was to just do total / id_count inside of the report itself, instead of attempting to do it through a dataset. It worked more easily and was less code intensive.

The problem with this, though, is that it doesn't accurately display the totals for all of the columns, now, only for each individual part in my table. Which brings me back to scripting probably being the easiest way to handle this solution cleanly and finally, instead of a makeshift solution that only works in a given environment.

Sometimes coming into a project fresh again in the morning is all it takes to solve a problem.

This is the final working version of what I was attempting to do. Neater code and working through stuff in multiple steps fixed the issue.

	counts = data['part_count'].getCoreResults()
	rows = counts.rowCount
	
	header = ['total', 'late', 'on_time']
	
	fixed = []
	for row in range(rows):
		temp = []
	
		id_count = counts.getValueAt(row, 'id_count')
		late_count = counts.getValueAt(row, 'late')
		total_count = counts.getValueAt(row, 'total')
		on_time_count = counts.getValueAt(row, 'on_time')
		
		fixed_late = late_count / id_count
		fixed_total = total_count / id_count
		fixed_on_time = on_time_count / id_count
		
		temp.append(fixed_total)
		temp.append(fixed_late)
		temp.append(fixed_on_time)
		
		fixed.append(temp)
		
	
	fixed_dataset = system.dataset.toDataSet(header, fixed)
	
	data['counts'] = fixed_dataset	

Simply divides the counts by the id_count. id is something that can be repeated if one of our employees clocks into the same part multiple times for this report, but if they only clocked in 1 time, quantity divided by 1 is still the quantity, while every other case will give an accurate quantity count.

The following query is how we pull the counts to start with.

select
sum(quantity) as total,

sum(
	case 
		when date_scheduled < completion_date
			then quantity
		else 0
	end) as late,
		
sum(
	case
		when date_scheduled >= completion_date
			then quantity
		else 0
	end) as on_time,
	
count(id) as id_count
	
from masterfabparts2 m, partsworkedon p where completion_date >= ? and completion_date <= ? and m.id = p.part_id_mf and p.username = ?
group by id
1 Like