Adding Text Annotations on Ignition Report Trends
Sometimes we want to annotate a value on a trend chart. Common annotations are the min/max value of a trend line, the point where something was changed, when a production run started, or when an alarm was triggered. While annotations aren’t built directly into the reporting module, it’s very easy to implement using the scripting functionality on the trend component.
The first step is to add a report with a trend chart—and a datasource to populate the trend. In this example, we will use a Tag History Query:
Next, add a trend chart to your report in the design view, and map the properties accordingly. In this case we are using the "temperature" tag from the "tag_history" data key.
Check the chart using Preview mode to should see the trend populate with data:
To make annotations, we need to use scripting on the trend component. To enable scripting, go back to the property pane in the Design tab, click "Enabled" under the "Scripting" section:
Click the "Edit Scripting" button to access the script editor, and paste in the code below to look like the following:
This script will annotate your chart with a callout of the maximum value along with a timestamp of when the value occurred. You can add similar annotations for minimum values, or pull in other records from a database, other tags, or any other datasource you might have. The callout will look like this when using the script:
If all you need is a max value annotation then you can stop here.
If you need more information, we'll dive into the script in a little more detail. This first section imports everything we need to handle reading data from the chart, building the annotation text, and adding the annotation to the chart:
from datetime import datetime
from java.util import Date
from org.jfree.ui import TextAnchor
from org.jfree.chart.annotations import XYTextAnnotation
from java.text import SimpleDateFormat
Next we will grab the XYPlot from the chart, so we can start digging into the data. Once we have this we can also pull out the dataset:
plot = chart.getXYPlot()
dataset = plot.getDataset()
Then, we’ll loop through the dataset to find the maximum value across the whole range of the trend. For a max value, we are checking to see if the current value is higher than the previous max, starting with 0, updating the max value, and grabbing the index in the dataset so we can properly align the annotation:
max=0
j=-1
for i in range(dataset.getItemCount(0)):
if dataset.getYValue(0,i)>max:
max = dataset.getYValue(0,i)
j=i
Finally we build the annotation. First we use the index of the max value from above to get the timestamp from the dataset at that index. Then, we format the timestamp into hours and minutes. Next, we build the text string for the annotation to include the maximum value as well as the timestamp. Lastly, we set the properties of the annotation, and add it to the chart.
timestamp = dataset.getXValue(0,j)
format = SimpleDateFormat("HH:mm")
label = XYTextAnnotation("Max Value: "+str(round(max,2))+" @ "+format.format(timestamp),timestamp, max)
label.setTextAnchor(TextAnchor.BOTTOM_LEFT)
plot.addAnnotation(label)
If you need to add more annotations to the chart, you can easily add more tracking similar to the example code for finding the max value, grab data from a database, or any other number of functions you can use in Ignition scripting. Once you have all of the data, you would generate additional annotations as needed, and add them all to the chart in the script.
from datetime import datetime
from java.util import Date
from org.jfree.ui import TextAnchor
from org.jfree.chart.annotations import XYTextAnnotation
from java.text import SimpleDateFormat
plot = chart.getXYPlot()
dataset = plot.getDataset()
max=0
j=-1
for i in range(dataset.getItemCount(0)):
if dataset.getYValue(0,i)>max:
max = dataset.getYValue(0,i)
j=i
timestamp = dataset.getXValue(0,j)
format = SimpleDateFormat("HH:mm")
label = XYTextAnnotation("Max Value: "+str(round(max,2))+" @ "+format.format(timestamp),timestamp, max)
label.setTextAnchor(TextAnchor.BOTTOM_LEFT)
plot.addAnnotation(label)