How can we get the X axis labels to line up on an even time interval, such as 5 minute intervals?
The graph includes:
- A numeric X axis - multiple numeric Y axes.- multiple ScatterLineSeries - Series data in an observable collection of datapoints having - Date time - date time of the data point (computed by StartTime + elapsed minutes) - The X axis is bound to this - Elapsed minutes - number of minutes from the start time (double) - Start time - DateTime of the first data point in the series (DateTime) - DataValue - value to display on the chart (double) - The Y axis is bound to this The data points are collected in real time and can come in at any time. The first data point in the series will be on an odd boundary, such as 3:41:20pm, instead of a rounded 3:30:00pm.
What we want is the X axis to start on an even boundary, such as 3:40:00pm and have labels at even intervals, 3:45:00pm, 3:50:00pm, 3:55:00pm...
We cannot use a CategoryDateTimeXAxis because the data points do not fall on even boundaries (i.e., there is no nicely aligned time value to bind the X axis to and the number of data points in a given time interval may vary).
The X axis labels in the middle of the chart are not on even boundaries if you set the X axis minimum or maximum or both.
Is there a way to make the Numeric X axis labels occur on even 5 minute boundaries?
Can this be accomplished by adding a hidden ScatterLineSeries with data points on 5 minute intervals and use that data series as the one the X axis uses for its labels?The numeric X axis should let us set the interval for labels since it appears that Infragistics will arbitrarily map the label to a nearby data point's X value. That mapping does not work well for evenly spacing labels and for a consistent user interface especially when zooming in.
The help has: In NumericXAxis, data is treated as continuously varying numerical labels, and the marker is placed at a point along the X-axis which varies according to the value in a data column that is mapped using the XMemberPath property of Scatter Series.
Hello,
I am checking if this is still an issue for you.
If you require any further assistance please do not hesitate to ask.
Here is a sample application main window c# and XAML. We want to set the X axis to start on an even 5 minute boundary and also have 5 minute intervals between X axis labels. The out of the box behavior appears to not let us set a starting value for the X axis and an interval that matches a date/time boundary. In other words, when showing more than a hour of real time collected data, we do not want to show the end user odd time icrement labels such as 12:37:32.
using System;using System.Collections.ObjectModel;using System.Windows;
namespace ScatterWithTextOnXAxis{ /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent();
DateTime start = new DateTime(2012, 04, 17, 12, 32, 31, 0); ObservableCollection<Data> graphData = new ObservableCollection<Data>();
graphData.Add(new Data{ Y = 1, TimeValue = start });
//we want the first X axis label to start on 12:30pm on Apr 17, 2012 //we want the other X axis labels on the graph to be on even 5 minute boundaries //New data points would be added to the collectio about 1 each second (but not guaranteed on each and every second)
int ctr = 1; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.63) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(1.13) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.23) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.56) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.90) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(1.42) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.03) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.24) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(1.55) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.34) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.78) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.90) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.21) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(2.63) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.04) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.37) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(1.60) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start}); start= start.AddMinutes(0.63) ; graphData.Add(new Data { Y = ctr++ * 5, TimeValue = start});
DataContext = graphData; } }
public class Data { public double X { get { return TimeValue.Ticks; } } public double Y { get; set; } public DateTime TimeValue { get; set; } }}
<Window xmlns:ig="http://schemas.infragistics.com/xaml" x:Class="ScatterWithTextOnXAxis.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" xmlns:local="clr-namespace:ScatterWithTextOnXAxis"> <Grid> <ig:XamDataChart> <ig:XamDataChart.Axes> <ig:NumericXAxis x:Name="xAxis" /> <ig:NumericYAxis x:Name="yAxis" /> </ig:XamDataChart.Axes> <ig:XamDataChart.Series> <ig:ScatterLineSeries ItemsSource="{Binding}" XAxis="{Binding ElementName=xAxis}" YAxis="{Binding ElementName=yAxis}" XMemberPath="X" YMemberPath="Y"/> </ig:XamDataChart.Series> </ig:XamDataChart> </Grid></Window>
I have been looking into your issue and I have created a sample application(DataChartRealData.zip) using the provided code. To set start date as 12:00 I have set the ‘MinimumValue’ of the XAxis to “start.AddMinutes(-2).AddSeconds(-31).Ticks” and its ‘MaximumValue’ to “start.AddMinutes(2).Ticks”.
For 5 minutes interval I have set its ‘Interval’ property to “3000000000”.
If you have any other questions on this matter, feel free to ask.
We did extensive investigation of this and whether or not it was worth it to access the not-acessable interval property in the axis via a custom dependency property.
Can the xamDataChart control be updated for the real-world scenario of real-time data acquisition for a time based X-Axis as well as an elapsed minutes X-Axis?
Both of those would not work with a category X Axis because there may be a variable time gap between data points.
This would help the real-world use of having multiple Y-axes and a single time or elapsed minutes based X-axis
We had to do the following complex solution for xamDatachart v12.1 on WPF:
- Set numeric X axis minimum and maximum to align the min/max visible with even number/time boundaries- Set numeric Y axis minimum and maximum to align the min/max visible with even number/time boundaries
- Override the TickMarkValues and generate by hand - the labels visible (major tickmark values) on the X and Y axes - the minor tickmark values for X and Y axes- Handle multiple graph related events (zoom, redraw axis panel, etc) to call the custom code to regenerate the major and minor tickmark values
This is overly complex in that we need to have business logic in our view model to handle user settable values (e.g., major/minor interval, starting value, ending value) as well as ones at the view level (major and minor tickmarks, start and end rounding).
--Recommendation--This could much more simply be handled if xamDatachart allowed a numeric X or Y axis to have a custom virtual method to let the user override the minimum and maximum visible (i.e., allow rounding to even numbers) as well as set the interval for major tickmarks/labels and the interval for minor tickmarks.
This would be much easier than having each part done in different event handlers.
Infragistics could help greatly if it was in this form and called by the graph control when needed (i.e., zoom, pan, new data added causing axis visible range to change, ...)
void GenerateVisibleAxisLabelsTickmarks(NumericAxisBase axis, ref double startingVisibleValue, ref double endingVisibleValue, ref double majorInterval, ref double minorInterval)
{ //values passed in are current values for the axis (eigther a numeric Y or numeric X axis
//round startingVisibleValue down to the nearest multiple of ...1000, 100, 10, 1/10, 1/100, ...
//round endingVisibleValue up the the nearest multiple of ...1000, 100, 10, 1/10, 1/100, ...
//round majorInterval to be divisible into the range (endingVisibleValue - startingVisibleValue)
//round minorInterval to be divisible into majorInterval
if (it is an X axis and X axis is time based) (i.e., it is using time.ticks for its values, which are then convereted to a date/time via a label converter)
{
//round to x hours, 1 hour 30 minutes, 15 minutes, 10 minute, 5 minutes, 1 minute, 30 seconds, 15 seconds, 10 seconds, 5 seconds, 1 second, 1/10 second, 1/100 second, ...
}
This is what is needed to handle a graph with dynamically added data where data is added at non-uniform intervals.
any solution for this issue? i am having the same problem
Jason,
Unfortunately the only way you can customize the labelling on the CategoryDateTimeXAxis at present is through the manipulation of the min/max/interval, but this doesn't allow you to shorten the first interval of the axis.
If you always want to snap the values in certain ways we'll need to provide you a customization hook by which you can decide where to place each gridline and label. The NumericXAxis actually has this, you can override its "TickmarkValues" and returrn a list of positions to label/gridline. You could actually use the NumericXAxis for labelling, if you desire, even if you don't associate it with the series you are displaying. You could set its minimum and maximum equal to the tick value of the actual min and max of the date time x axis, and then override the TickmarkValues in order to have fine grained control over which labels get displayed. The other piece of the puzzle would be to use a converter with the axis to convert the ticks values into the appropriate date time strings.
Doing the above would be somewhat complicated, but is achievable. As an alternative option, you could make a feature request for the labelling behavior you are trying to achieve. There is a "calendar axis" on our backlog I believe, which may be defined to support features such as this, but the more feature requests we receive the more it should help set the backlog priority.
-Graham
Graham,
Thanks for the reply. I do have MinimumValue and MaximumValue available to me, but using these as a solution to my problem proved to be inadequate. I don't want to limit the range of data that's visible, I just want to alter the labeling. Also, even if I set the min and max, zooming on the chart presents the same problems with labeling that I've had. Is there any way to specify a label start offset?
Thanks,
Jason