JfreeChart Dataset

Scripting JfreeChart using component property change.

The issue is that it throws in AttributeError when I try to access the dataset of chart.
Chart is located inside a template which has property change script :


and has a datasets :
image
Here, the the init of the LabTestChart looks like -

at the end of the init, i’m trying to set the the dataset as:
image
which throws an error saying there is no attribute named Specs.
am I missing something here ?

Debugging this,
Also got to know that I can’t actually access any property of the chart

This is a ‘Classic’ Chart component? The datasets work a bit differently, for complicated backend reasons. Try using self.chart.setPropertyValue("Specs", data)

I tried that,

throws an exceptions as :

12:44:11.429 [AWT-EventQueue-0] ERROR com.inductiveautomation.ignition.client.util.gui.ErrorUtil - <HTML>Error executing script for event:&nbsp;<code><b>propertyChange</b></code><BR>on component:&nbsp;<code><b>TorqueChart</b></code>.
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last):
  File "<event:propertyChange>", line 5, in <module>
  File "<module:LabTesting>", line 87, in __init__
AttributeError: 'org.jfree.chart.JFreeChart' object has no attribute 'setPropertyValue'

and yes,
It’s a Classic chart.

You may need to bring it up a level when you feed your class (event.source).

I’m guessing that the Specs dataset can be calculated directly from within property change event. What are you trying to do that requires a class?

True, Doesn’t need a class to do this little but setting the dataset from component event doesn’t work either.
For example,
I am running property change script on root container of the template which sets the value of the dataset. When I test it, I can see it’s initializing since the number on Y-axis changes as per the data but I don’t see the chart coming up.
image

Can you post the script and some sample data for me to look at? You can PM it to me if you don’t want to make it public.

I’m not having an issue using a property change event.

For those awaiting news, the root cause is that the data that needed to be displayed, can’t be displayed due to null values interspersed within the dataset. Separating them out to individual datasets solved the problem.

Dynamically adding datasets to a classic chart doesn’t exist, but could be helpful. Link to entry on ideas site, if one wants to upvote this.

https://ideas.inductiveautomation.com/ignition-features-and-ideas/p/add-datasets-to-classic-chart-via-scripting

Well, actually :nerd_face:
You could call getDynamicProps(), which returns a TreeMap<String, DynamicPropertyDescriptor>, then add your own DynamicPropertyDescriptor to the map, and then apply it back to the chart with setDynamicProps(). Use the four argument constructor for com.inductiveautomation.factorypmi.application.binding.DynamicPropertyDescriptor - DynamicPropertyDescriptor("name", "description", com.inductiveautomation.ignition.common.Dataset, <your dataset>)

2 Likes

I had started poking around the javadocs, but then it was lunchtime. Priorities!

Also, wondering if there is a way to put legends on the chart itself like matplotlib.

RectangleEdge has only 4 fields which are too basic.

HA !!! I am 0 in Java (I mean Java is Chinese to me), so, it was nice learning !

from java.lang import Boolean
from java.lang import Boolean
import org.jfree.chart.annotations.XYLineAnnotation as XYLineAnnotation
from org.jfree.chart.plot import CategoryPlot
import java.beans.FeatureDescriptor
import com.inductiveautomation.factorypmi.application.binding.DynamicPropertyDescriptor as DynamicPropertyDescriptor
chartObj = event.source.parent.getComponent('Chart')

chart = chartObj.chart
plot = chart.getXYPlot()

DynamicPros = chartObj.getDynamicProps()

values = DynamicPros.values()

oneValue = values[0]
print 'DynamicPros - ' + str(DynamicPros)

print 'DynamicPros Values - ' + str(values)

DynamicProperty = DynamicPropertyDescriptor()

DynamicProperty.setName('MyTrial')
DynamicProperty.setShortDescription('Just Specifications')

DynamicProperty.setPropertyType(oneValue.getPropertyType())

DynamicProperty.setValue([[],[]])

DynamicPros.put('specTrial',DynamicProperty)

chartObj.setDynamicProps(DynamicPros)

DynamicPros = chartObj.getDynamicProps()

print 'DynamicPros - ' + str(DynamicPros)

doing this I was able to get this :

DynamicPros - {Spec1: Spec1, Spec2: Spec2, Spec3: Spec3}
DynamicPros Values - [Spec1, Spec2, Spec3]
DynamicPros - {Spec1: Spec1, Spec2: Spec2, Spec3: Spec3, specTrial: MyTrial}

and checked that I have a newly created dataset.

one question - I kind of cheated at DynamicProperty.setPropertyType(oneValue.getPropertyType())

What will be the actual syntax to add property type ?

Thanks in advance

You can simplify it by constructing the DynamicPropertyDescriptor in one go:

from com.inductiveautomation.factorypmi.application.binding import DynamicPropertyDescriptor
from com.inductiveautomation.ignition.common import Dataset

chartObj = event.source.parent.getComponent('Chart')
chart = chartObj.chart
plot = chart.getXYPlot()

props = chartObj.getDynamicProps()

values = props.values()

print 'Props - ', props
print 'Props Values - ', values

dataset = system.dataset.toDataSet([], [[]])
newProp = DynamicPropertyDescriptor("myTrial", "Description", Dataset, dataset)

props.put('specTrial', newProp)
chartObj.setDynamicProps(props)

print 'Updated Props - ', chartObj.getDynamicProps()

Hi, i am using classic chart in vision … in easy chart units of the tags will show in y axis(note - only if tags has different units its will show separate Y axis for each)

I am trying to achieve same thing in classic chart (is there any jfree script to achieve my requirement)

i am trying to show separate Y axis for tags if units are different

can you please help me out in this

Put them in separate dataset properties. Then you can configure the units separately.

Yes for each tag i have separate dataset. I have 3 tags so i created 3 dataset and 3 x axis and 3 yaxis… But i want to show 3 y axis only if 3 tags has different units… If 3 tags has same unit… Then i have to use one y axis for all tags…

Whether i understood your reply or i am saying any wrong ? …

Please give your suggestion to find solution for my issue

Put all tags with same units in the same dataset. Put tags with different units in different dataset. I don’t think there is any other solution for the classic chart.

I can’t do like that i am doing offset for each tag soo i have to use single dataset for each tag

Move your raw data bindings to custom properties on the container or some other component. Script the construction of a merged dataset for the chart when any raw data changes.

Raw data bindings - you mean dataset which i have for each tag?
I have to merge the dataset for tags showing same unit right?