Overlaying non-associated Alarms on Trends

If you're just wanting a visual reference when a tag was in an alarmed state, I imagine the simplest solution would be to place some value and interval markers on the easy chart.

Example:
• Add a button to the window, and give it two custom properties: alarmPath and journalData
image

• Perform a journal query from the button's action performed event handler using the easyChart's start and end date as well as the button's alarmPath property to filter the data:

easyChart = event.source.parent.getComponent('Easy Chart')
startDate = easyChart.startDate
endDate = easyChart.endDate
alarmPath = event.source.alarmPath
def getJournalData(start = startDate, end = endDate, alarm = alarmPath):
	journalData = system.alarm.queryJournal(journal = 'Journal', startDate = start, endDate = end, path = alarm).dataset
	def setJournalData():
		event.source.journalData = journalData
	system.util.invokeLater(setJournalData)
system.util.invokeAsynchronous(getJournalData)

• Create a couple of custom methods [or library scripts] for adding markers to the chart's plot:

addIntervalMarker custom method

#def addIntervalMarker(self, startDate, endDate):
	from org.jfree.chart.plot import IntervalMarker
	faultColor = system.gui.color(255, 0, 0, 100)
	plot = self.parent.getComponent('Easy Chart').getComponent(0).getComponent(0).chart.plot
	plot.addDomainMarker(IntervalMarker(system.date.toMillis(startDate), system.date.toMillis(endDate), faultColor))

addValueMarker custom method

#def addValueMarker(self, date):
	from org.jfree.chart.plot import ValueMarker
	from java.awt import BasicStroke
	chartX = system.date.toMillis(date)
	plot = self.parent.getComponent('Easy Chart').getComponent(0).getComponent(0).chart.plot
	faultColor = system.gui.color('red')
	valueMarker = ValueMarker(chartX)
	valueMarker.setStroke(BasicStroke(3))
	valueMarker.setPaint(faultColor)
	plot.addDomainMarker(valueMarker)

• Finally, add the markers to the chart using the journalData property change event in the propertyChange event handler:

if event.propertyName == 'journalData':
	easyChart = event.source.parent.getComponent('Easy Chart')
	
	# Reset existing domain markers
	plot = easyChart.getComponent(0).getComponent(0).chart.plot
	plot.clearDomainMarkers()
	
	# Locate all the active to not active intervals,
	# and put the start and end of each in a list
	journalData = event.newValue
	intervalList = []
	currentStartDate = None
	for row in xrange(journalData.rowCount):
		eventTime = journalData.getValueAt(row, 'EventTime')
		eventState = journalData.getValueAt(row, 'EventState')
		if eventState > 1 and not currentStartDate:
			currentStartDate = eventTime
		elif eventState < 2 and currentStartDate is not None:
			intervalList.append([currentStartDate, eventTime])
			currentStartDate = None
	
	# If the last entry is alarmed, extend the alarm to the end of the chart
	if currentStartDate:
		intervalList.append([currentStartDate, easyChart.endDate])
	
	# Iterate through the intervals and mark the chart
	for interval in intervalList:
		alarmStart, alarmEnd = interval
		event.source.addIntervalMarker(alarmStart, alarmEnd)
		event.source.addValueMarker(alarmStart)
		event.source.addValueMarker(alarmEnd)

Result:

Edit: Improved interval segmenting logic

2 Likes