Please see http://ubermind.com/~xenakis/chart.png for reference.
The chart seen is one weeks worth of data (Fri 00:00 hours thru Thu 23:00 hours) points taken on an hourly basis. The chart is an XYPlot w/ Y NumberAxis and an X HorizontalDateAxis. The ticks mark the beginning of each day and the vertical lines mark 6-hour increments.
The data points are set by incrementing "hourly" from the 00:00 hour on the first day thru the 23:00 hour on the last... which are the same values I use as the lower and upper range for the axis. I turned off the auto-range to prevent the hard-coded HorizontalDateAxis margin from appearing.
The TickUnit is (Calendar.DATE, 1); however, the minimum date (for the axis) is 12:00 noon on Fri and the maximum date is 12:00 noon on Thu. The idea is to have the ticks labels rendered at the 12:00 noon "mark" for each day rather than the 00:00 hour (which is what its doing now), but I just can't seem to make it work.
Am I missing something? Is this not possible? Hope that's enough info... thanks in advance.
mx.
Can't center Day Names on HorizontalDateAxis
Re: Can't center Day Names on HorizontalDateAxis
Unfortunately the HorizontalDateAxis class marks the beginning of each period. I will be rewriting the code before 1.0.0 (to incorporate tick unit collections the way NumberAxis works) so I'll see then if I can add an option to put the tick labels in the middle of each period.
Regards,
DG.
P.S. In CVS now, you can control the margins for the auto range on the date axis. This will be included in 0.9.3.
Regards,
DG.
P.S. In CVS now, you can control the margins for the auto range on the date axis. This will be included in 0.9.3.
Re: Can't center Day Names on HorizontalDateAxis [WORKAROUND
Well, I come up w/ a workaround for this ... let's see if I can describe it coherently.
In the beginning the series I fed into the XYPlot use a java.lang.Long as the x-value. The value stored w/in is the milliseconds from 1/1/19070 of the Date of data-point. I normalize the dates by creating a GregorianCalendar object using the Date of the first data-point and setting its HOUR, MINUTE, SECOND and MILLISECOND fields to zero.
The timeInMillis value of the above Date is then the long which is used for the first data-point; as I'm graphing hourly data, x-value for each point is derived by adding 3,600,000 to each previous x-value (the # of millis in an hour.)
The min and max dates for the HorizontalDateAxis were set as the Date referenced above and a similarly "normalized" date (but one week later), respetively.
I also explicitly set the range of the axis. The lower being the timeInMillis value for the min date and the upper being the timeInMillis of the max date w/ the HOUR_OF_DAY field (this done via a GregorianCalendar object) set to 23, i.e. the last hour of the day.
The result was that the tick marks were graphed w/ the first data-point for each day. (Sorry if all this repetition is redundant, but wanted to be clear.)
So here's the punch line:
When creating the XYSeries, I simply offset the x-value for the data points by (-)43,200,000 - or the number of milliseconds in 12 hours. similiarly the lower and upper range values of the axis were offset by this same number, and the TickUnits then align themselves w/ the appropriate x-values of the data points. The result can be seen here: http://ubermind.com/~xenakis/chart.png.
You might also notice an alternating "intensity" of the vertical lines. I'm not sure if such functionality is anywhere w/ the APIs, but the algorithm was pretty simple. For anyone interested, here's the method I use to do that:
static public void generateVerticalLinesForPlot(XYPlot plot, ArrayList seriesInterval, Vector increments, Vector colors) {
int seriesSize = seriesInterval.size();
for (int idx = 0; idx < seriesSize; idx++) {
for (int iidx = 0; iidx < increments.size(); iidx++) {
int curIncrement = ((Integer)increments.get(iidx)).intValue();
if (idx == (((idx + 1) / curIncrement) * curIncrement)) {
Color curColor = (Color)colors.get(iidx);
if (curColor != null) {
long intervalValue = ((Number)seriesInterval.get(idx)).longValue();
plot.addVerticalLine(new Long(intervalValue), curColor);
}
break;
}
}
}
}
And the code to call it:
Vector increments = new Vector();
Vector colors = new Vector();
increments.add(new Integer(24));
increments.add(new Integer(12));
increments.add(new Integer(6));
colors.add(new Color(102, 102, 102));
colors.add(null);
colors.add(new Color(204, 204, 204));
RTPChartUtilities.generateVerticalLinesForPlot(plot, seriesInterval, increments, colors);
Note that the increments refer to the index of the seriesInterval. In the case, each element w/in represents an x-value and they are regularly distributed.
cheers.
mx.
In the beginning the series I fed into the XYPlot use a java.lang.Long as the x-value. The value stored w/in is the milliseconds from 1/1/19070 of the Date of data-point. I normalize the dates by creating a GregorianCalendar object using the Date of the first data-point and setting its HOUR, MINUTE, SECOND and MILLISECOND fields to zero.
The timeInMillis value of the above Date is then the long which is used for the first data-point; as I'm graphing hourly data, x-value for each point is derived by adding 3,600,000 to each previous x-value (the # of millis in an hour.)
The min and max dates for the HorizontalDateAxis were set as the Date referenced above and a similarly "normalized" date (but one week later), respetively.
I also explicitly set the range of the axis. The lower being the timeInMillis value for the min date and the upper being the timeInMillis of the max date w/ the HOUR_OF_DAY field (this done via a GregorianCalendar object) set to 23, i.e. the last hour of the day.
The result was that the tick marks were graphed w/ the first data-point for each day. (Sorry if all this repetition is redundant, but wanted to be clear.)
So here's the punch line:
When creating the XYSeries, I simply offset the x-value for the data points by (-)43,200,000 - or the number of milliseconds in 12 hours. similiarly the lower and upper range values of the axis were offset by this same number, and the TickUnits then align themselves w/ the appropriate x-values of the data points. The result can be seen here: http://ubermind.com/~xenakis/chart.png.
You might also notice an alternating "intensity" of the vertical lines. I'm not sure if such functionality is anywhere w/ the APIs, but the algorithm was pretty simple. For anyone interested, here's the method I use to do that:
static public void generateVerticalLinesForPlot(XYPlot plot, ArrayList seriesInterval, Vector increments, Vector colors) {
int seriesSize = seriesInterval.size();
for (int idx = 0; idx < seriesSize; idx++) {
for (int iidx = 0; iidx < increments.size(); iidx++) {
int curIncrement = ((Integer)increments.get(iidx)).intValue();
if (idx == (((idx + 1) / curIncrement) * curIncrement)) {
Color curColor = (Color)colors.get(iidx);
if (curColor != null) {
long intervalValue = ((Number)seriesInterval.get(idx)).longValue();
plot.addVerticalLine(new Long(intervalValue), curColor);
}
break;
}
}
}
}
And the code to call it:
Vector increments = new Vector();
Vector colors = new Vector();
increments.add(new Integer(24));
increments.add(new Integer(12));
increments.add(new Integer(6));
colors.add(new Color(102, 102, 102));
colors.add(null);
colors.add(new Color(204, 204, 204));
RTPChartUtilities.generateVerticalLinesForPlot(plot, seriesInterval, increments, colors);
Note that the increments refer to the index of the seriesInterval. In the case, each element w/in represents an x-value and they are regularly distributed.
cheers.
mx.