|
X axis with time values |
Posted by Massimo on Apr-16-2013 00:32 |
|
Hi,
I am trying to display a scattered chart where the Y axis has standard double values and the X axis as TIME ONLY values (e.g. 08:18 or o8:32 etc..)
The scatter chart has 4 layers: one for morning, one for afternoon etc..
I am not bothered about the labels but about the Data.
I have tried to use dataX0 = Chart.CTime2(MorningDates.ToArray()); but I get all values displayed at the very right margin of the chart
can anyone help ? below the code I am using
*****************************************************
dataX0 = Chart.CTime2(MorningDates.ToArray());
dataX1 = Chart.CTime2(AfternoonDates.ToArray());
dataX2 = Chart.CTime2(EveningDates.ToArray());
dataX3 = Chart.CTime2(NightDates.ToArray());
dataY0 = Morning.ToArray();
dataY1 = Afternoon.ToArray();
dataY2 = Evening.ToArray();
dataY3 = Night.ToArray();
double[] labels = {00,01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24};
// Create a XYChart object of size 800 x 360 pixels. Use a vertical gradient
XYChart c = new XYChart(800, 360);
// color from sky blue (aaccff) to white (ffffff) as background. Set border to
// grey (888888). Use rounded corners. Enable soft drop shadow.
c.setBackground(c.linearGradientColor(0, 0, 0, c.getHeight(), 0xaaccff, 0xffffff
), 0x888888);
c.setRoundedFrame();
c.setDropShadow();
// Set the plotarea at (100, 80) and of size 600 x 230 pixels, with white
// (ffffff) background. Use grey #(aaaaa) dotted lines for both horizontal and
// vertical grid lines.
c.setPlotArea(100, 80, 600, 230, 0xffffff, -1, -1, c.dashLineColor(0xaaaaaa,
Chart.DotLine), -1);
// Add a legend box with the bottom center anchored at (300, 80) (top center of
// the plot area). Use horizontal layout, and 8 points Arial Bold font. Set
// background and border to transparent.
LegendBox legendBox = c.addLegend(300, 80, false, "Arial Bold", 8);
legendBox.setAlignment(Chart.BottomCenter);
legendBox.setBackground(Chart.Transparent, Chart.Transparent);
//Add a title to the chart using 14 points Times Bold Itatic font
c.addTitle("Blood Glucose History for 2013", "Arial Bold", 14);
//'Reserve 10% margin at the top of the plot area just to make sure the line does
//'not go too near the top of the plot area
c.yAxis().setAutoScale(0.1);
//Add a title to the y axis. Draw the title upright (font angle = 0)
c.yAxis().setTitle("Values (mmol/L)", "Arial Bold", 12).setFontAngle(90);
c.xAxis().setTitle("Hour of measurement", "Arial Bold", 12);
c.xAxis().setLabels2(labels, "{value}");
//Set the axes line width to 3 pixels
c.xAxis().setWidth(3);
c.yAxis().setWidth(3);
//Add an orange (0xff9933) scatter chart layer, using 13 pixel diamonds as //symbols for morning
LayerMorning = c.addScatterLayer(dataX0, dataY0, "Morning", Chart.DiamondSymbol, 9, 0xff9933);
//Add a green (0x33ff33) scatter chart layer, using 11 pixel triangles as symbols for aftermoom
LayerAfternoon = c.addScatterLayer(dataX1, dataY1, "Afternoon", Chart.SquareSymbol, 9, 0x33ff33);
//Add a blue (0X7AA4D5) scatter chart layer, using 11 pixel triangles as symbols for evening
LayerEvening = c.addScatterLayer(dataX2, dataY2, "Evening", Chart.TriangleSymbol, 9, 0X7AA4D5);
//Add a black (0X000000) scatter chart layer, using 11 pixel triangles as symbols for night
LayerNight = c.addScatterLayer(dataX3, dataY3, "Night", Chart.InvertedTriangleSymbol, 9, 0XFFFF00);
//output the chart
ChtMatrix.Image = c.makeWebImage(Chart.PNG); |
Re: X axis with time values |
Posted by Peter Kwan on Apr-16-2013 01:42 |
|
Hi Massimo,
I assume MorningDates are really dates according to .NET syntax (that is, contains elements of type System.DateTime). In this case, the labels and setLabels are not necessary. These two lines in fact set the x-axis to be from 0 to 24, which are not suitable for date or time.
Plesae try to remove the line 'c.xAxis().setLabels2(labels, "{value}");'. Instead, please use:
c.xAxis().setDateScale(startDate, endDate, 86400)
c.xAxis().setLabelFormat("{value|hh}")
If you want the x-axis to auto-scale as a date/time axis, you may also use:
c.xAxis().setDateScale3("{value|hh:nn}")
Hope this can help.
Regards
Peter Kwan |
Re: X axis with time values |
Posted by Massimo on Apr-16-2013 16:07 |
|
Hi Peter,
many thanks for your reply. Of course let me stress that I am doing some trial and error here as I am not quite in sync with Chart Director
I tried to clean up my code from all the different tries I had and I have produced a version with your suggestions, but seems I am doing something very wrong as you can see from the attached screenshot; all values are on the right side of the chart.
Below the updated code.
************************************
private void DrawChart(DataTable DtChartToDraw)
{
//Y axis Lists
List<Double> Morning = new List<double>();
List<Double> Afternoon = new List<double>();
List<Double> Evening = new List<double>();
List<Double> Night = new List<double>();
//X axis Lists
List<DateTime> MorningDates = new List<DateTime>();
List<DateTime> AfternoonDates = new List<DateTime>();
List<DateTime> EveningDates = new List<DateTime>();
List<DateTime> NightDates = new List<DateTime>();
//Arrays for the X axis bar chart
DateTime[] dataX0 = new DateTime[] { };
DateTime[] dataX1 = new DateTime[] { };
DateTime[] dataX2 = new DateTime[] { };
DateTime[] dataX3 = new DateTime[] { };
//Arrays for the Y axis bar chart
Double[] dataY0 = new Double[] { };
Double[] dataY1 = new Double[] { };
Double[] dataY2 = new Double[] { };
Double[] dataY3 = new Double[] { };
//Min and Max dates boundary
DateTime MinDate = DateTime.MinValue;
DateTime MaxDate = DateTime.MinValue;
// Layer LayerMorning ;
// Layer LayerAfternoon;
// Layer LayerEvening;
// Layer LayerNight;
for (int counter = 0; counter <= DtChartToDraw.Rows.Count - 1; counter++)
{
//Patient Reading Values
double Value = Convert.ToDouble(DtChartToDraw.Rows[counter]["Value"].ToString());
//the 4 timespan for Morning,Afternoon,Eveing and night (e.g. 08:00 - 12:00)
string TimeSpan = DtChartToDraw.Rows[counter]["TimeSPan"].ToString();
//the Date and Time of each recording
DateTime TimeStamp = DateTime.Parse(DtChartToDraw.Rows[counter]["TimeStamp"].ToString(), CultureInfo.CreateSpecificCulture("en-GB"));
//get min and max Date value
if (TimeStamp < MinDate)
MinDate = TimeStamp;
if (TimeStamp > MaxDate)
MaxDate = TimeStamp;
//Hour = Convert.ToInt32(DtChartToDraw.Rows[counter]["Hour"].ToString());
if (TimeSpan == GetEnumDescription(TimeSpans.Morning))
{
Morning.Add(Value);
MorningDates.Add(TimeStamp);
}
if (TimeSpan == GetEnumDescription(TimeSpans.Afternoon))
{
Afternoon.Add(Value);
AfternoonDates.Add(TimeStamp);
}
if (TimeSpan == GetEnumDescription(TimeSpans.Evening))
{
Evening.Add(Value);
EveningDates.Add(TimeStamp);
}
if (TimeSpan == GetEnumDescription(TimeSpans.Night))
{
Night.Add(Value);
NightDates.Add(TimeStamp);
}
}
dataX0 = MorningDates.ToArray();
dataX1 = AfternoonDates.ToArray();
dataX2 = EveningDates.ToArray();
dataX3 = NightDates.ToArray();
dataY0 = Morning.ToArray();
dataY1 = Afternoon.ToArray();
dataY2 = Evening.ToArray();
dataY3 = Night.ToArray();
String[] labels = {"00","01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17",
"18", "19", "20", "21", "22", "23", "24"};
// Create a XYChart object of size 800 x 360 pixels. Use a vertical gradient
XYChart c = new XYChart(800, 360);
// color from sky blue (aaccff) to white (ffffff) as background. Set border to
// grey (888888). Use rounded corners. Enable soft drop shadow.
c.setBackground(c.linearGradientColor(0, 0, 0, c.getHeight(), 0xaaccff, 0xffffff
), 0x888888);
c.setRoundedFrame();
c.setDropShadow();
// Set the plotarea at (100, 80) and of size 600 x 230 pixels, with white
// (ffffff) background. Use grey #(aaaaa) dotted lines for both horizontal and
// vertical grid lines.
c.setPlotArea(100, 80, 600, 230, 0xffffff, -1, -1, c.dashLineColor(0xaaaaaa,
Chart.DotLine), -1);
// Add a legend box with the bottom center anchored at (300, 80) (top center of
// the plot area). Use horizontal layout, and 8 points Arial Bold font. Set
// background and border to transparent.
LegendBox legendBox = c.addLegend(300, 80, false, "Arial Bold", 8);
legendBox.setAlignment(Chart.BottomCenter);
legendBox.setBackground(Chart.Transparent, Chart.Transparent);
//Add a title to the chart using 14 points Times Bold Itatic font
c.addTitle("Blood Glucose History for 2013", "Arial Bold", 14);
//'Reserve 10% margin at the top of the plot area just to make sure the line does
//'not go too near the top of the plot area
c.yAxis().setAutoScale(0.1);
//Add a title to the y axis. Draw the title upright (font angle = 0)
c.yAxis().setTitle("Values (mmol/L)", "Arial Bold", 12).setFontAngle(90);
c.xAxis().setTitle("Hour of measurement", "Arial Bold", 12);
// c.xAxis().setLabels2(labels, "{value}");
c.xAxis().setDateScale(MinDate, MaxDate, labels);
c.xAxis().setLabelFormat("{value|hh}");
c.xAxis().setDateScale3("{value|hh:nn}");
//Set the axes line width to 3 pixels
c.xAxis().setWidth(3);
c.yAxis().setWidth(3);
//Add an orange (0xff9933) scatter chart layer, using 13 pixel diamonds as //symbols for morning
c.addScatterLayer(Chart.CTime(dataX0), dataY0, "Morning", Chart.DiamondSymbol, 9, 0xff9933);
// LayerMorning.setXData(dataX0);
//Add a green (0x33ff33) scatter chart layer, using 11 pixel triangles as symbols for aftermoom
c.addScatterLayer(Chart.CTime(dataX1), dataY1, "Afternoon", Chart.SquareSymbol, 9, 0x33ff33);
//LayerAfternoon.setXData(dataX1);
//Add a blue (0X7AA4D5) scatter chart layer, using 11 pixel triangles as symbols for evening
c.addScatterLayer(Chart.CTime(dataX2), dataY2, "Evening", Chart.TriangleSymbol, 9, 0X7AA4D5);
// LayerEvening.setXData(dataX2);
//Add a black (0X000000) scatter chart layer, using 11 pixel triangles as symbols for night
c.addScatterLayer(Chart.CTime(dataX3), dataY3, "Night", Chart.InvertedTriangleSymbol, 9, 0XFFFF00);
// LayerNight.setXData(dataX3);
//output the chart
ChtMatrix.Image = c.makeWebImage(Chart.PNG);
}
***************************************
|
Re: X axis with time values |
Posted by Massimo on Apr-16-2013 17:32 |
|
Ok..
I have managed to get the values correctly on the chart by cheating a bit.
Basically I am passing hors and minutes as double like 8.12 rather than 08:12
So the values are now displaying fine as per the attached screenshot.
My problem now is the format of the X labels; I am using this line
c.xAxis().setLabels2(labels, "{value|0:00.0}");
where "labels" is an arrays of Double like this
Double[] labels = {00,01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
however I get 1 2 3 4 etc... rather than 01 02 03 etc....
How can I have 01 02 03 using Double as type ?
|
Re: X axis with time values |
Posted by Massimo on Apr-16-2013 17:40 |
|
OK,
I solved this by using setLabels which accept an array of strings .
c.xAxis().setLabels(labels); |
Re: X axis with time values |
Posted by Peter Kwan on Apr-17-2013 01:07 |
|
Hi Massimo,
In your earlier code, the MinDate is set up incorrectly. In your code, you use:
DateTime MinDate = DateTime.MinValue;
It should be:
DateTime MinDate = DateTime.MaxValue;
If your initialize MinDate to be the MinValue, the following code would not work:
if (TimeStamp < MinDate)
MinDate = TimeStamp;
It is because if the MinDate is already the MinValue, it is not possible for your TimeStamp to be smaller than MinValue, so the "if" condition can never be true. If the above code does not work, then the MinValue does not reflect your actual data.
The code "c.xAxis().setDateScale(MinDate, MaxDate, labels);" is probably incorrect, because it assumes MinDate to MaxDate is 24 hours. But in your code, MinDate and MaxDate are from your actual data, and they are not 24 hours (it is from 9:12am to 22:13pm).
Also, from the table below, it also seems your data are for many days (Dec 18, 2012 to Mar 19, 2013), not just 24 hours. If you just want to plot the "hour of day", you may set the date part to a constant date (such as Jan 1, 2013 or any arbitrary date) before passing the dates to ChartDirector.
For the setDateScale, it is better to set the startDate as Jan 1, 2013 00:00:00 and the endDate as Jan 2, 2013 00:00:00, covering 24 hours. So for your case, MinDate and MaxDate should be unnecessary.
Anyway, if your data are within 24 hours, instead of using DateTime, it is OK to use a number representing the elasped hours since midnight. For example, if the elapsed time is 2:30, you may use 2.5 hours (2 hours 30 minutes is equal to 2.5 hours). In this case, 8:12 should be represented as 8 + 12/60.0, not 8.12.
Hope this can help.
Regards
Peter Kwan |
Re: X axis with time values |
Posted by Massimo on Apr-17-2013 01:21 |
|
Hi Peter,
now I feel like a dummy for the MinDate
anyway, I can only thank you for your answer and I will give it another try tomorrow using DateTime values rather than double as I am doing now.
as for the plot data, is not just 24 hours, is anything within a date range choose by the user. Basically these values are Blood glucose recordings entered from the user; they can have N number of recordings per day. Clinicians wanted 4 time span like morning afternoon evening and night.
to summarize, the Y axis has the recorded value (Doubles) and the X axis the time and minutes of the recording. |
Re: X axis with time values |
Posted by Peter Kwan on Apr-17-2013 03:15 |
|
Hi Massimo,
I understand the your "raw data" contain different dates. However, it seems you just want to plot the points using the time of day and ignore the date part. In other words, the position of a data point does not depend on the date. The position only depends on the time of day.
In ChartDirector, the x-data value specifies the position of the data point. As the position does not depend the date part, your code cannot pass the actual date to ChartDirector. It should just pass the time of day. It is OK to use a number 0 to 24 to represent the time of day in hour units.
If you would like to use DateTime, because in .NET, the DateTime must have a date part, so your code must still include a "dummy" date in the DateTime values. The actual date is not important, so long as all the x-coordinates has the same date. The date I suggest Jan 1, 2013 is just for convenience. You can use any other date. It does not matter. (The constant date is just added to satisfy the .NET requiement that DateTime must have a date part, and to reflect that the data position does not depend on the date part.)
Personally, for your case, I would prefer to use the number 0 to 24 representing the time of day in hours instead of using DateTime (which forces us to add a dummy date).
Regards
Peter Kwan |
Re: X axis with time values |
Posted by Massimo on Apr-17-2013 15:44 |
|
Hi Peter,
you are right in what you are saying; the only note is that I have to take into account hours and minutes.
The solution you are suggesting in adding a dummy date plus the correct time values as DateTime is smart and I will try to implement it today.
The solution I am using in passing time values as double seems to work, but I am concerned about loss of value precision in doing it in this way.. will 08:30 be represented on the graph in the same way of 08.30? Logically I would say no, but seems to work
By the way, I am using the version 5.0.2.0 of ChartDirector; unfortunately my Company, University of Dundee, does not want to buy a new license.
Not sure if you are the right person to address this question: do you know if there is an academic license that I can buy myself and if so the price of it ? |
Re: X axis with time values |
Posted by Peter Kwan on Apr-18-2013 03:03 |
|
Hi Massimo,
If you are using time of day as the x-axis, then 08:30 is exactly the same as 8.5 hours. Therefore the chart is exactly the same, that is, the position of all the points are the same no matter you use DateTime or numbers. The only difference is the default "labelling" of the chart. For example, if you add popup tooltips for the data points, if you use DateTime, the data value can be displayed as {value|hh:nn} (which will display 08:30). If you use numbers (0 to 24), you may display the data value as {value} (which will display 8.5). In the latter case, if you want the tooltip to show "08:30" even if your data value is 8.5, you may use {={value}*3600+0.4|hh:nn}.
For the licensing, I will forward your enquiry to sales@advsofteng.net. Please expect an email response within a few hours.
Regards
Peter Kwan |
Re: X axis with time values |
Posted by Massimo on Apr-18-2013 05:25 |
|
you are actually anticipating my question as I was thinking to use tooltips for the points on the scatter chart; the problem is that in theory patients may have numerous recordings within a short space of time, so the chart may be really cluttered with points.
As for thye labels, the format of 01 02 03 etc.. has been chosen by my Line Manager, so I have to comply even if I do not totally agree with it |
|