Set X-Trace on Easy Chart to specific date/time

Can the X-Trace marking on the Easy Chart be set to a specific date and time?
I've been digging around in the API and I can't seem to find a way to specify the X-Trace via scripting.

I've got a customer who wants to show an alarm journal underneath the historian screen, and if an alarm is clicked on, then show/move the X-Trace marking to the date and time of the alarm.

This sort of thing is exactly what my NoteChart module was designed to support, including the scriptable XTrace timestamp. (I'd show the alarm events as notes, though, to save screen real estate.)

Thanks for the info. I'll pass that along to them and see what they say.

Can you share any way I can set the XTrace on the IA Supplied EasyChart? Or is there no easy way to do it natively?

I honestly would have expected changing the plot's domainCrosshairValue to move the xTrace, but I couldn't get it to work event with a repaint. What I did get to work was calculating the x-coordinate from the domain location and simulating a mouse click using robot. Here is the custom method I developed that simply requires the specified date in millis to be passed in:

def setXTrace(self, timeStampInMillis):
	from java.awt import Robot
	from java.awt.event import MouseEvent
	
	# Get the internal EasyChart Class, the JFreeChart, and the plot
	chartField = self.getClass().getDeclaredField('chart')
	chartField.setAccessible(True)
	easyChartPanel = chartField.get(self)
	chart = easyChartPanel.chart
	plot = chart.plot
	
	# Calculate the x-coordinate based on the time in millis
	xCoordinate = int((timeStampInMillis - plot.domainAxis.lowerBound) / (plot.domainAxis.upperBound - plot.domainAxis.lowerBound) * easyChartPanel.width)
	
	# Create a robot for simulating mouse events
	robot = Robot()
	
	# Simulate a mouse click event at the calculated x-coordinate within the easyChart
	robot.mouseMove(easyChartPanel.locationOnScreen.x + xCoordinate, easyChartPanel.locationOnScreen.y)
	robot.mousePress(MouseEvent.BUTTON1_MASK)
	robot.mouseRelease(MouseEvent.BUTTON1_MASK)

Alternatively, you could simply draw a value marker on the chart to mark the location of the alarm event. Here is an example I developed for the easy chart that you could possibly adapt to your requirement:

1 Like

Thanks, I'll take a look at those as well.

In case you are still curious, I figured out that it's the chart panel's setAnchor method that can be used to programmatically set the xTrace. However, it's not exposed, so reflection has to be used to invoke it, and it uses a Point2D.Double to position the range and domain crosshairs. Therefore, just like the robot method I developed, any timestamp has to be converted to a x coordinate to correctly position the domain crosshair on the chart. Also, in my testing, I found that a repaint is needed to make the effect immediately observable.

Thanks!

I've not had enough time to take a look. Next week should be slower though and I should be able to try it.

I found some time this morning to install the note chart module in my test environment, and that is by far the simplest approach. All you have to do to move the xTrace is change the traceTS parameter, and it takes a normal and natural date without any convert to millis or x-coordinate hocus pocus:

newDate = # Alarm event active time
event.source.parent.getComponent('Easy Note Chart').traceTS = newDate
1 Like

It came to my attention that the xCoordinate calculation for the robot method listed above could be a little off due to the variable plotData position within the chartPanel. This can be corrected easily with the screenDataArea, but messing around with it, the approach didn't feel complete because of these reasons:
• The mouse cursor jumping to the chart and not staying at the click point was a bit jarring
• If the alarm date wasn't displayed on the chart the mouse cursor would move off screen
• If the chart wasn't already in xTrace mode, nothing would happen.

The following updated approach corrects all of those issues, centers the alarm date on the chart, and puts the xTrace there without the need for any complicated calculations. It also takes a normal unformatted date:

#def setXTrace(self, date):
	'''
	This is designed to be placed in a custom method on the chart itself
	'''
	from java.awt import Robot, MouseInfo
	from java.awt.event import MouseEvent
	
	# Get the mouse's current location, so it can be put back after the chart has been clicked
	eventLocation = MouseInfo.getPointerInfo().location
	
	# Ensure that the chart is in xTrace mode
	self.setMode(4)
	
	# Reposition the plot, so the selected date and time is centered
	# ...with exactly one day's worth of data visible
	startDate = system.date.addHours(date, -12)
	endDate = system.date.addHours(date, 12)
	self.startDate = startDate
	self.outerRangeStart = startDate
	self.endDate = endDate
	self.outerRangeEnd = endDate
	
	# Get the internal EasyChart class
	easyChartPanel = self.getComponent(0).getComponent(0)
	
	# Get the data area and calculate the coodinates for the exact midpoint of the plotted data
	# ...using the data area bounds and the chart's location on the screen
	dataArea = easyChartPanel.screenDataArea
	xCoordinate = int(easyChartPanel.locationOnScreen.x + dataArea.x + (0.5 * dataArea.width))
	yCoordinate = int(easyChartPanel.locationOnScreen.y + dataArea.y + (0.5 * dataArea.height))
	
	# Create a robot instance
	robot = Robot()
	
	# Ensure that the mouse is not still being pressed by the user before moving the cursor
	# ...This line was added to correct a behavior that occurred during testing
	robot.mouseRelease(MouseEvent.BUTTON1_MASK)
	
	# Move the mouse to the midpoint of the plot
	robot.mouseMove(xCoordinate, yCoordinate)
	
	# Click the mouse button to move the xTrace
	robot.mousePress(MouseEvent.BUTTON1_MASK)
	robot.mouseRelease(MouseEvent.BUTTON1_MASK)
	
	# Move the mouse back to its starting location
	robot.mouseMove(eventLocation.x, eventLocation.y)