Web forum is in read-only mode. Login as active registered customer for write access
  Forum Search   New Posts New Posts

X Axis as Time

 Post Reply Post Reply
Author
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Topic: X Axis as Time
    Posted: 26 Feb 2016 at 6:59am
Hi, after a couple of days of trying to get this I resort to asking. I have searched the forum and read the developer guide ad infinitum.
I am trying to plot numbers vs time. At the moment the Date/Time is column 0 of my AdvStringGrid and I am choosing column 3 as my values. Time format in col 0 is 16/02/2016 21:05:02 etc. Values in column 31 vary between and 24.
Question 1: The panes->Range->RangeFrom/RangeTo. I would have assumed these were TDateTime variables and indeed when I use the start and end times for my data the X axis shows those correct times. However it shows no data values. If I change RangeFrom/RangeTo to be integers, ie my sample numbers (1 through 1600) then I get the chart shown but the X Axis values are wrong. They start at 12/09/00 and go through 15/03/04. It seems I get one or the other.
Question 2: The function s->AddSinglePoint(latest,timeSample); should timeSample be a string or a TDateTime variable? Again it does not seem to affect the outcome above, the manual says TDateTime but some answers Bruno gives on the forum say it is just a string.

The code I am using is as follows. I don't think the casting I have done really does anything, but I tried everything I could.
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Extended value;
double max,min,latest;
String St="12.5";
String strCell;
int cnt;
TDateTime rangeStart,rangeEnd,timeSample;
cnt = weatherChart->Panes->Count;
weatherChart->BeginUpdate();
weatherChart->Panes->Clear();
weatherChart->Panes->Add()->Series->Add();
int i;
TChartPane *p = weatherChart->Panes->Items[0];
TChartSerie *s = p->Series->Items[0];
s->LegendText = "Hello";
TextToFloat(St.c_str(),&value,fvExtended);
rangeStart = chartGrid->Cells[0][1];
for(cnt=1;cnt<chartGrid->RowCount-1;cnt++){
strCell = chartGrid->Cells[3][cnt];
TextToFloat(strCell.c_str(),&value,fvExtended);
latest = (double)value;
timeSample = (TDateTime)(chartGrid->Cells[0][cnt]);
s->AddSinglePoint(latest,timeSample);
if(cnt==1)rangeStart = timeSample;
rangeEnd = timeSample;
}
p->Range->RangeFrom = 1;//rangeStart;
p->Range->RangeTo = cnt-1;//rangeEnd;
p->XAxis->UnitType = utDay;
p->YAxis->AutoSize = arEnabled;
p->YAxis->AutoUnits = true;
s->ChartType = ctLine;
s->AutoRange = arEnabled;
s->LegendText = "Humidity";
s->XAxis->MajorUnitTimeFormat = "DD/MM/YY";
//max = s->SerieMax();
//min = s->SerieMin();
//s->SerieType = stBoth;
weatherChart->EndUpdate();
//p->CrossHair->CrossHairType = chtFullSizeCrossHairAtCursor;
//p->CrossHair->CrossHairYValues->ShowSerieValues;
//p->CrossHair->Visible = true;

}
//---------------------------------------------------------------------------




Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 8:43am
Hi, 

There are 2 demo's included in the distribution on how to add a datetime x-axis as well as a tip at the following page:

Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 9:25am
You are correct that there are demos, which I looked at. However I don't think they really address the question. The thing that I missed was the Range.StartDate which in my case is 16/02/2016 21:00:02 so I assume that if I use the RangeFrom as 0 it sets this point as this Date/Time. Then depending on the value of XAxis->UnitType it adds a day(utDay) or a minute (uTMinute) to that DateTime to get the date/time for sample 1 etc. Your example is very simplistic in that it adds one day at a time and you have a complete data set. In my case the samples can occur at asynchronous times, but all registered by the correct DateTime stamp. Also some samples may be missing. Using the theory that I have arrived at above, AdvCharts cannot cope with my data. Is this so? Otherwise it has to associate each record, in your example 0 to 30 with the real TDateTime and it does not seem to do that in my case. Sorry if i am missing something but I can't see it
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 9:36am
The Range.StartDate in combination with the UnitType, and the Range.RangeFrom / Range.RangeTo create an X-Axis with date/time values equally distributed. if Range.RangeTo is 60 and the unit type is utMinute it will create an X-Axis with 60 minutes starting from the Range.StartDate. You can add points by passing a timestamp within the Range.StartDate to Range.StartDate + 60 minutes to the AddSingleXYPoint overload, but then you will need to switch to ctXYLine instead.
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 10:24am
Thanks Peter, I have been trying the AddXY points, was trying to make some sense of the format for it from the demo of XY time.  The developer manual just states that it is overloaded, all sorts of combinations seem to compile and give weird results. The Delphi code in the demo is
      begin
        d := EncodeTime(10, 0, 0, 0) + (1 / 24 / 60 * c);
        c := c + (Random(5) + 1);
        AddSingleXYPoint(0, Random(100), EncodeTime(10, I, 0, 0), d);
      end;
The developer manual has AddSingleXYPoint(SingleXPoint, SingleYPoint: double); so the X value is first, so for the demo
So do I assume that the first parameter is always 0? What is it? The second Random(100) must be the Y value which seems at odds with the manual, the third parameter is the X value as TDateTime, why a fourth parameter which is also TDateTime.  Please give me some help here, the function may be overloaded but so is my brain. Thanks
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 10:30am
The AddSingleXYPoint can also be used for gantt charts, therefore 2 timestamp parameters can be used. For a ctXYLine, you can use the following overload, only using the Y-value and the first timestamp parameter:

AddSingleXYPoint(0, Random(100), d, 0);

Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 10:49am
Peter, taking all that into account, could you please explain why my code will not work. I am setting the UnitType to uTDay and the RangeTo as 3, so that should give me a range of 3 days from my start date? I am using the ChartType ctXYLine.
I then put in my values using s->AddSingleXYPoint(0,latest,timeSample,0); latest is type double, timeSample is type TDateTime. I don't see any values displayed on the chart, X axis is as I would expect, start date + the three days
TDateTime rangeStart,rangeEnd,timeSample;

cnt = weatherChart->Panes->Count;

weatherChart->BeginUpdate();
weatherChart->Panes->Clear();
weatherChart->Panes->Add()->Series->Add();

int i;
TChartPane *p = weatherChart->Panes->Items[0];
TChartSerie *s = p->Series->Items[0];
s->LegendText = "Hello";

TextToFloat(St.c_str(),&value,fvExtended);
rangeStart = chartGrid->Cells[0][1];
p->Range->StartDate = rangeStart;
p->Range->RangeFrom = 0;//rangeStart;
p->Range->RangeTo = 3;//cnt-1;//rangeEnd;
p->XAxis->UnitType = utDay;
p->YAxis->AutoSize = arEnabled;
p->YAxis->AutoUnits = true;
s->ChartType = ctXYLine;
s->AutoRange = arEnabled;
s->LegendText = "Humidity";
s->XAxis->MajorUnitTimeFormat = "dd/mm/yyyy";
for(cnt=1;cnt<chartGrid->RowCount-1;cnt++){
strCell = chartGrid->Cells[3][cnt];
TextToFloat(strCell.c_str(),&value,fvExtended);
if((double)value > max)max = value;
if((double)value < min)min = value;
latest = (double)value;
timeSample = (TDateTime)(chartGrid->Cells[0][cnt]);
// s->AddSinglePoint(latest,timeSample);
s->AddSingleXYPoint(0,latest,timeSample,0);
if(cnt==1)rangeStart = timeSample;
  // rangeEnd = timeSample;
}
//max = s->SerieMax();
//min = s->SerieMin();
//s->SerieType = stBoth;
weatherChart->EndUpdate();
 
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 11:03am
Hi, 

The overload accepts additional parameters. It seems in C++ that the overload needs a specific type casting to TDateTime. Additionally, since the RangeTo is set to 3, it will only try to display 3 points, which means that you need to force the chart to use the full range of points. Included is a working sample on a default chart in C++

int cnt;
cnt = weatherChart->Panes->Count;

weatherChart->BeginUpdate();
weatherChart->Panes->Clear();
weatherChart->Panes->Add()->Series->Add();

int i;
TChartPane *p = weatherChart->Panes->Items[0];
TChartSerie *s = p->Series->Items[0];
s->LegendText = "Hello";

TDateTime rangeStart = EncodeDate(2016, 2, 26);
p->Range->StartDate = rangeStart;
p->Range->RangeFrom = 0;
p->Range->RangeTo = 3;
p->XAxis->UnitType = utDay;
p->YAxis->AutoSize = arEnabled;
p->YAxis->AutoUnits = true;
s->ChartType = ctXYLine;
s->AutoRange = arEnabled;
s->UseFullRange = True;
s->LegendText = "Humidity";
s->XAxis->MajorUnitTimeFormat = "dd/mm/yyyy";
for(cnt=0;cnt<25;cnt++){
TDateTime timeSample = IncHour(rangeStart, cnt * 3);
s->AddSingleXYPoint(0,Random(100),timeSample,TDateTime(0));
}
weatherChart->EndUpdate();
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 11:16am
Thanks Peter, it works but I really can't see any difference to mine except the casting on the final parameter in the AddSingleXYPoint function. But I will chase it through and see where my error is.
Thanks for your help, I will report back
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 11:38am
Peter, I am going to give up for the night now, getting late. Your example works, If I change your for(cnt=0 loop to pick up my data as follows;
for(cnt=1;cnt<chartGrid->RowCount-1;cnt++){
strCell = chartGrid->Cells[3][cnt];
TextToFloat(strCell.c_str(),&value,fvExtended);
latest = (double)value;
TDateTime timeSample = (TDateTime)chartGrid->Cells[0][cnt];
//TDateTime timeSample = IncHour(rangeStart, cnt * 3);
s->AddSingleXYPoint(0,latest,timeSample,TDateTime(0));
}
When I use your line with the IncHours, ie setting a regular increment, I get a chart displayed. If I substitute my line picking up the time from the grid, which is already in TDateTime format but I cast it again for good measure, I get X axis as expected, showing the dates for the 3 days and I get the Y axis scaled according to my data. But no trace. The only difference I can see is that you are using exact, regular, no missing sample data, I am using asynchronous, sample missing data. It is very late here so I am going to turn off the lights and go home but if you can see any difference I would certainly appreciate it.
Thanks

Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 11:40am
Hi, 

To skip data, you need to add an additional Defined parameter added to the AddSingleXYPoint overload, this in case there is no data for that specific time. 
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 11:42am
My timeSample has resolution down to seconds as well, where you are only using to hours, but I would not have thought that was an issue. Thanks
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 12:02pm
Hi, 

You can add time in seconds, the data was only a quick sample, but when the datetime is 0, the data is always added, therefore you need to manually add an "undefined" point.
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 12:08pm
So can I clear this up. If I have to put in any missing points, which is a hassle since I would have to really go through my whole data set looking for missing points. What if the points are not falling completely synchronously. Ie, what if my time values are 10:15:00, 10:20:00, 10:22:00, 10:30:00 etc, is it going to cope with that, because I really will be using the AddXYPoint data with that irregularity. I suspect that is where the issue is? When I started out here I was expecting that the X axis was composed of TDateTime values but it really is a value representing the sample number and I think that is where my understanding is conflicting with TMS reality?

If that is the case, what if I use TDBAdvCharts? I am assuming that I can set my data base there to have a column which is the time value which could be asynchronous. Does it pick up and use the asynchronous, missing data or do I have to tidy it all up before calling the chart?

Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 12:14pm
The values for the ctXYLine chart type can be added with different intervals. You should be able to add the values you mention without any issue, yet when having a point that doesn't not have a valid value or datetime, adding that point will result in a line drawn, therefore in your loop, you only need to make sure you are adding valid points, and add an undefined point for the invalid points. The DB chart currently doesn't support XY charts. This behavior would need to be manually implemented by using a first.. next statement and fetching the data from the database.
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 12:15pm
An undefined point is a point that is added through the AddSingleXYPoint overload, but with a True flag passed as a parameter to one of the overloads. Included is a sample that demonstrates. When running the sample you will notice a hole that is formed by undefined points. The undefined points are now simulated, but the check that is now if (cnt > 10 && cnt < 20) { should be replaced with a check if the points coming from the grid are valid, for example, if the timestamp in the grid is not an empty string. Additionally, you can see the timestamp that is being passed is randomly increased with a range from 1 to 10 hours. You only need to make sure that the next point that is added does not have a timestamp in the past (before the previous point).

int cnt;
cnt = weatherChart->Panes->Count;

weatherChart->BeginUpdate();
weatherChart->Panes->Clear();
weatherChart->Panes->Add()->Series->Add();

int i;
TChartPane *p = weatherChart->Panes->Items[0];
TChartSerie *s = p->Series->Items[0];
s->LegendText = "Hello";

TDateTime rangeStart = EncodeDate(2016, 2, 26);
p->Range->StartDate = rangeStart;
p->Range->RangeFrom = 0;
p->Range->RangeTo = 5;
p->XAxis->UnitType = utDay;
p->YAxis->AutoSize = arEnabled;
p->YAxis->AutoUnits = true;
s->ChartType = ctXYLine;
s->AutoRange = arEnabled;
s->UseFullRange = True;
s->LegendText = "Humidity";
s->XAxis->MajorUnitTimeFormat = "dd/mm/yyyy";
TDateTime timeSample = rangeStart;
for(cnt=0;cnt<30;cnt++){
timeSample = IncHour(timeSample, RandomRange(1, 10));
if (cnt > 10 && cnt < 20) {
s->AddSingleXYPoint(0,Random(100),timeSample,TDateTime(0), False);
}
else
{
s->AddSingleXYPoint(0,Random(100),timeSample,TDateTime(0));
}
}
weatherChart->EndUpdate();


Edited by Pieter Scheldeman - 26 Feb 2016 at 12:21pm
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 26 Feb 2016 at 1:10pm
Thanks Peter, I will go through your example tomorrow. Late here. I have my code working. Problem was you had your start date as 26/2/2016 which I did not notice, the start dates in my table are 16//2/2016 which explains why the values were not showing as they were off the range.
I replaced my casting of my time cell with StrToDateTime(chartGrid->Cells[0][cnt]) and that is creating a proper point.
Home now, eyballs hanging on desk but thanks

Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 27 Feb 2016 at 4:06am
Peter, when I add a cross hair to the project you provided at 11:03 am yesterday on this issue, using the code
s->ShowValueInTracker = true;
p->CrossHair->CrossHairType = chtSmallCrossHair;
p->CrossHair->CrossHairYValues->ShowSerieValues = true;
p->CrossHair->CrossHairYValues->Position = p->CrossHair->CrossHairYValues->Position << chValueTracker;
p->CrossHair->Visible = true;
The values at the cross hair do not correspond to the position on the chart, they represent values to the right of the crosshair by a substantial amount, about half a day. I saw this in my own code, suspected I had an error and then went back and ran your code again and see the same problem, can you see it too or is it something at this end. In my real data it corresponds to about 12 hours difference on the x axis. Is there a chance the crosshair is not converting between am and pm?
Thanks
robyn

Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 29 Feb 2016 at 12:05am
I have found the answer to the last question. It involves the XScaleOffset factor. There is no mention of what this is in the developers manual. There is a brief mention that it was added as a new feature in the history. What does it do? By implementing the line p->XScaleOffset = false; i correct the problem but what am I actually doing. Is the offset settable somewhere?
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 29 Feb 2016 at 10:21am
The offset is not settable, the XScale starts at point 0 which is already offset by the widh of the series rectangle divided by the amount of visible points. When XScaleOffset is set to False, the first point starts at 0 pixels, instead of the XScale in pixels.
Back to Top
Hannah Robyn View Drop Down
New Member
New Member
Avatar

Joined: 17 Mar 2011
Posts: 15
Post Options Post Options   Quote Hannah Robyn Quote  Post ReplyReply Direct Link To This Post Posted: 29 Feb 2016 at 11:56am
So the original question remains unanswered, the offset has nothing to do with the crosshair picking up the wrong values, it was coincidence that the offset seems to be a bout 12 hours in pixels. Please look at the original question 27 Feb at 4:06am
Back to Top
Pieter Scheldeman View Drop Down
TMS Support
TMS Support
Avatar

Joined: 18 May 2010
Posts: 3574
Post Options Post Options   Quote Pieter Scheldeman Quote  Post ReplyReply Direct Link To This Post Posted: 29 Feb 2016 at 12:19pm
The X/Y charts support and date/time for line and marker were added afterwards and the initial design did not allow values to be painted with different XScales, Therefore we have introduced the XScaleOffset property which can be used to starting drawing at 0 or at XScale. We are unaware of any crosshair issues, but we will investigate what goes wrong here. 

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down