* * *

Author Topic: TAChart: Changing standard time/date format for time axis  (Read 6126 times)

wp

  • Hero Member
  • *****
  • Posts: 3667
Re: TAChart: Changing standard time/date format for time axis
« Reply #15 on: August 09, 2016, 03:56:24 pm »
Initially, I was confused by the naming (TFixedIntervalChartSource), and by your description of a constant count of labels, because after zooming the count of labels changes. But after some playing I was beginning to see the point: If you zoom around a labeled point, then the label is still existing afterwards. In the builtin algorithm, however, this label usually disappears after zooming.
Oh I'm so stupid - I did not reckognize that the Intervals.Options only uses aipUseCount in your example. In the default settings, the axis behaves normally, in my eyes. So, I fear I still do not understand the advantage of your labeling algorithm. You say above: "the grid really always is constant." - but what I see in your demo: it is not, it is changing like with the builtin-labeling routine.
Lazarus trunk / fpc 3.0.0 / Win32

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #16 on: August 09, 2016, 04:07:57 pm »
I guess its better to not consider the logarithmic algorithm first, otherwise its too much at the same time...

Then this a severe weakness of the algorithm, it MUST be able to produce better results than the builtin algorithm automatically.
Well, the purpose was not to beat the built-in (automatic) algorithm:-) Perhaps I have to explain the purpose better. I designed the algorithm actually only for zooming purpose, as in the non-zoomed state the grid/labels should be fully (100%) under user control. Consider the case the user wants to plot something depending on an angle. Desired grid positions are 0;45;90;135;180. For angles these are 'natural' positions. Therefore he chooses the range 0 to 180 (degree) and GridCount to 4, thats it. The grid is forced to these values, as the intervals are fixed in length (thats why I chose the name FixedIntervalChartSource). And the intervals are not just constant but are actually user defined through the bounds and the GridCount. In my opinion a quite intuitive approach for the user.
When zooming then some automatism is needed, and as a different GridCount is not critical there, the algorithm suits quite good, I think. The case of automatic axis scaling can be deemed as zooming. The GridCount couldn't be kept, but more important the grid values still fit to the data, as they are always interpolated from the 'home' window. Through this interpolation the grid always fits to the data, but an explicit definition of the 'home' window is needed.

On the oposite with an fully automatic grid arrangement such label positions would be difficult to realise. Or even imagine positions of 0;22.5;45...
In the automatic system, gridCount couldn't be applied to strict, otherwise the labels get ugly. So how to realise such a spacing?

BTW: How does your algorithm behave if max is positive and min is negative? Does it produce a label to be at 0?
I just had to check that in the demo. You can play around with the bounds, thats why I placed the EditBoxes in the demo.
It actually does force a label to zero, which I consider as bug, as it reduces user controlability:-)

Here is my idea.
Your algorithm always spans the grid starting from 0 and guarantees a constant grid. I think this is very nice! The built-in algorithm could come up with something like 0;0.4;0.7;1, which is very nasty. I'd appreciate a demo implementation ;-)

Perhaps I can also use your approach to optimise the speed in my algorithm, as now the interpolation is somehow iterative.

Note that the first and last label are always beyond the real axis range. They will not be painted anyway, but are required in order to fill the space to the first/last visible label with minor labels if needed.
Can you describe that more detailed? Whats the difference if its in the list and not?

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #17 on: August 09, 2016, 04:15:39 pm »
You were faster then me... Hope its clearer now.

I did not reckognize that the Intervals.Options only uses aipUseCount in your example.
When using the ChartSource then the Intervals.Options are useless anyways. But in unzoomed status it behaves exactly (!?) like [aipUseCount]. But zooming gets interesting then.

wp

  • Hero Member
  • *****
  • Posts: 3667
Re: TAChart: Changing standard time/date format for time axis
« Reply #18 on: August 09, 2016, 05:50:18 pm »
The grid is forced to these values, as the intervals are fixed in length
The first part of this sentence cleared my understanding, the second part is wrong. The advantage of your algorithm is not that the intervals are fixed in length, but that the labels are attached to the series. We were discussing zooming all the time, and this confused me because this is where different properties come into play. But if we look at panning then the difference is clear.

In the attachment there is a modification of the last demo uploaded. Now with a sine function, and ranging between -180 and 180. The program starts with your algorithm - labels are fine.

Then switch to standard labeling - the labels are fine as well because I selected Axis.Intervals.Options := [aipUseCount] (nothing else!), Axis.Intervals.Count = 4, and Chart.Margins.Left = 0 and .Right = 0 (this is because the built-in labeler puts the first/labels at the axis border if the aipUseCount option used, but the first/last datepoint is shifted in by Chart.Margins.Left/Right - probably a bug).

Now drag the curve by moving the mouse with the right button down. As you see: the standard labels are attached to the chart, not to the data, and immediately get very ugly.

Go back to your algorithm and drag: the labels move with the curve! This really is a great advantage and a strong argument for your ChartSource because it is a very natural behavior.

As for your question regarding the first and last label being outside the chart area: Each axis has a property Minors which you can use to add another set of ticks and labels and grid lines. I normally use it to draw minor ticks without labels and without grid lines - looks really good. These additional ticks/labels are drawn between the main labels. Therefore if the first label is inside the chart area then there are no minor ticks before it, the same with the last label.

I'll try to implement my algorithm of the previous post. Give me some time...
Lazarus trunk / fpc 3.0.0 / Win32

wp

  • Hero Member
  • *****
  • Posts: 3667
Re: TAChart: Changing standard time/date format for time axis
« Reply #19 on: August 09, 2016, 11:18:12 pm »
The attachment contains an extended version of your demo, now with a TAxisLabelChartSource as roughly described a few posts above. It has a property "Interval" which - if not zero - defines the fixed interval between the axis labels. This is only for very special cases because it does not change at all, even after zooming. Automatic scaling is activated if "Interval" is 0 and is determined by the StepCount and NiceSteps properties: StepCount is the same as your GridCount (I renamed it because I never knew whether it is the number of grid lines or spaces). NiceSteps is a string containing all allowed step values separated by a | character. The order of magnitude of these numbers is ignored. The algorithm seeks that step value and multipies it with the correct power of 10 such that the required StepCount is best approximated. The default is '1|2|5'; with the data in the demo where the axis ranges between -180 and 180 this means that the intervals can be 10, 20, 50, or 100 in principle; along with the given StepCount of 4 the algorithm selects 50. For a sine curve this is not very nice, it would be better to have multiples of 30, 60, or 90 --> Change NiceSteps to '3|6|9' (you can also use '30|60|90') --> voila!

There are some other parameter combinations for the built-in labeler. It can be seen that its default settings (top-most radiobutton) can produce similar results, also after panning, but it is extremely difficult to control the label spacing. The versions with aipUseNiceSteps only show only the center label, probably the MaxLength is essentially needed here.

BTW: the TAxisLabelChartSource the labels do not change when the window is increased because the chart size does not enter the calculation. This may be seen as an advantage (better controllability of label positions) or disadvantage (too sparse labels in case of large or even full-screen chart).
Lazarus trunk / fpc 3.0.0 / Win32

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #20 on: August 10, 2016, 09:53:27 pm »
BTW: the TAxisLabelChartSource the labels do not change when the window is increased because the chart size does not enter the calculation. This may be seen as an advantage (better controllability of label positions) or disadvantage (too sparse labels in case of large or even full-screen chart).
I guess we have three levels of automation now:
1. The build-in algorithm is fully automatic, number of labels, intervals etc. all is controlled by the algorithm, depending on data and size of chart. A custom manipulation is difficult.
2. Your algorithm which uses the StepCount as basis and does everything else automatic. Its easy adjustable to the data and gives more freedom for manual adjustment of the sizings in a simple way (using the StepCount).
3. My algorithm with manual set-up in the unzoomed state and full grid automation for zooming and panning. Therefore with more control of the grid in unzoomed state, but also more parameters needed.

I think in total having these three options is a very nice choice for the programmers! Do you see a chance (or advantage) to combine them in one class or would you rather keep it seperated? For the build-in one with options [aipUseCount,aipUseNiceSteps] I would actually expect a grid like calculated with your algorithm. For my algorithm in oposite I think its better to keep it separated as the parameters could get confusing.
On the otherhand using only the option [aipUseCount], then I would expect a behaviour like in my algorithm.


When I compared our two algorithms, I found that the use of StepCount is a bit different. In yours (we should really give them qualified names~) the StepCount is actually the minimum number of steps. When zooming, the actual step number may be the same or higher, but never less. In my implementation on the other hand for zooming its more like the avarage number, it could get lower and higher. I think both is reasonable, in my case the number is defined in the unzoomed state and when zooming, then in the first step the grid should get less. In your case the algorithm is quite nice using the minimum approach. For clearity it may be helpful to rename it to MinStepCount?

About the naming things: As I'm a 'new member' I hesitate with giving it a name, also its not so clear for me how to merge it into the TAChart component. Is there something like a standard procedure for such extensions/modifications? How to get 'agreement' from the developers?

Said that, here some proposals:
In my opinion the key difference in your algorithm in comparison to the built-in one is that the StepCount has to be defined, this makes it an interval chart source. As this class name already exists and this one is explicitly designed for an axis it could be Named TIntervalAxisSource.
For my algorithm it could be TManualIntervalAxisSource. But still FixedInterval is not that bad a name, I think, as it describes the function in the unzoomed state quite well.

About the StepCount/GridCount I still favour GridCount. In the TIntervalChartSource the parameter is just 'Count', especially derived in the TDateTimeIntervalChartSource its not so clear 'count' of what. I see it similar for StepCount: What 'steps'? Although its more precise if its for the number of intervals or number of grid bars, but when someone gets in touch with the parameter the first time, its more important to know what he can even influence with this parameter. IntervalCount might be an alternative.

Again about the parameters in my algorithm, in the current state, passing the bounds through AParams.FFullExtentMin doesn't work well, as the auto ranging will destroy the concept. If such parameters are used, then they should forward the explicit user settings in extent.XMin and Xmax (Because auto ranging is deemed as zooming). But this would cause trouble for Axis transformations. So I still think that dedicated parameters are more useful, even if its more difficult to understand the usage. Passing the extent on the other hand is also not very intuitive as the range also could be set in the axis parameters...
By the way, in the last two demos the manual bounds setting through the editboxes didn't work any more due to the auto ranging issue.

wp

  • Hero Member
  • *****
  • Posts: 3667
Re: TAChart: Changing standard time/date format for time axis
« Reply #21 on: August 10, 2016, 11:53:33 pm »
My problem is that the three axis labelers are very similar, and it will be very confusing for the users to select the one they need. We definitely must find speaking names and write good documentation.

I hesitate to integrate the new labelers into the TChartAxis code directly because this would blow up the Object Inspector with properties working only if the corresponding algorithm is active - I always hate that. And when working with the "hot" source there's always a risk of breaking something. Fortunately, TAChart is very modular and the labelers can be provided as separate components, maybe combined into a single component with an algorithm switch.

I am thinking of adding another operation mode to "my" algorithms in which labels are not determined by interval count but by interval width (in pixels, like the MaxLength/MinLength). This would make it very similar to the builtin algorithm. Ideally I'd get a better understanding of how the builtin algorithm works, and maybe I can fix it to do what we need, and then I could drop my algorithm altogether.

If my algorithm survives I'd try to squeeze in a logarithmic mode as well. Log axes really are a pain now.

I am still not happy with the fact that your algorithm requires user input. If data range is between 1 and 9 then you say somewhere above that a DefaultExtentMin/Max of 0 and 10 produce good results with StepCount=5. So, there must be some argument how to modify the extent limits. And then it can be coded as well!

As for the GridCount/StepCount/IntervalCount naming: GridCount is confusing me. What is this? There is only one grid, but several grid lines. And the number of grid lines is different from the number of intervals. IntervalCount probably is the best.
Lazarus trunk / fpc 3.0.0 / Win32

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #22 on: August 11, 2016, 12:51:47 am »
My problem is that the three axis labelers are very similar, and it will be very confusing for the users to select the one they need. We definitely must find speaking names and write good documentation.
Thats rigth, would be a pitty if its just not recognised by the users.

I hesitate to integrate the new labelers into the TChartAxis code directly because this would blow up the Object Inspector with properties working only if the corresponding algorithm is active - I always hate that.
I agree there should not be too much unused parameters. But your algorithm fits to the default parameters I'd say (Count, MinWidth...).

I am still not happy with the fact that your algorithm requires user input. If data range is between 1 and 9 then you say somewhere above that a DefaultExtentMin/Max of 0 and 10 produce good results with StepCount=5. So, there must be some argument how to modify the extent limits. And then it can be coded as well!
Its the basic idea of the algorithm that it adapts to the the user chosen bounds. So they have to be defined.
DefaultExtent 0 to 10 and IntervalCount=5 forces the grid to 0;2;4... If the range is between 1 and 9 then for the algorithm this is zooming/panning, so labels will be nice, for this specific example at the same positions starting with 2, but the number of labels are less (2;4..8 instead of 0;2..10). As input the algorithm only has DefaultExtent, IntervalCount and CurrentExtent (from AParams), nothing else. Try it with my first or second demo (only for X-axis) and change the bounds in the editfields in the running demo. You will see you have the full control over the label positions, which you don't have in any automatic setting (or if, then more complicated to realise). You want a grid over radian instead of degree then define DefaultExtentMin:=0, DefaultExtentMax:=6.282 IntervalCount:= 4 then labels will be at 0;Pi/2;Pi;3Pi/2;2Pi. When zooming they always stay but could get interpolated. If the actual grid is different, then it still works, but the labels may not on the edges anymore. Instead of DefaultExtentMin/Max it would also be possible to use two parameters IntervalWidth and AnchorPoint (Normally 0).

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #23 on: August 21, 2016, 12:38:50 pm »
There was a floating point problem e.g. resulting in 0.049999999999 instead of 0.05 when zooming-in. I fixed that with rounding. Also some of the variables I renamed in the hope that their purpose is more clear now. Attached the latest version and demo.

The extend has to be defined by the user using the parameters DefaultExtentMin and DefaultExtentMax.

From the functional side I would say its ready now. So there is still the question if it is possible/wished for to merge it into TAChart.

By now its not a visual component, but that somehow is related to the question TAChart or not.

wp

  • Hero Member
  • *****
  • Posts: 3667
Re: TAChart: Changing standard time/date format for time axis
« Reply #24 on: August 21, 2016, 04:56:47 pm »
Thank you for your effort. As for integration in TAChart, I'll try to combine your approach with mine to some universal axis labeling chartsource, or improve the built-in labeler if I can spot the point(s) where it goes crazy. In my eyes the built-in approach has all the ingredients needed, and it SHOULD work. One short-coming is that labels do not necessarily start at zero, i.e. label values should always be an integer multiple of the interval distance calculated. This would cure a large fraction of the issues. Your request of providing a fixed interval count could be added as other element of the Intervals.Options set. I'd prefer such a solution ("universal labeler", or improved built-in algorithm) over a standalone chartsource dedicated to a single, rarely used task jamming the component palette.

Unfortunately I am busy with other activities at the moment and cannot concentrate on this tricky issue. So, it may take some time until TAChart will have an improved labeling chart source. You'll have your own component for the meantime.
Lazarus trunk / fpc 3.0.0 / Win32

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #25 on: May 02, 2017, 10:44:17 pm »
Hello WP,

today I updated to Lazarus 1.6.4 FPC 3.0.2 SVN-Revision 54278 (official release). The property DateTimeStepFormat (class TDateTimeIntervalChartSource) you added on August last year seems to be gone in the new version.

Error message:
Quote
Error: identifier idents no member "DateTimeStepFormat".

Is this by mistake? Or is there an other way to use it?
Thank you!

Regards

wp

  • Hero Member
  • *****
  • Posts: 3667
Re: TAChart: Changing standard time/date format for time axis
« Reply #26 on: May 05, 2017, 06:06:59 pm »
Please re-read reply #1 (last paragraph)
Lazarus trunk / fpc 3.0.0 / Win32

kupferstecher

  • Jr. Member
  • **
  • Posts: 97
Re: TAChart: Changing standard time/date format for time axis
« Reply #27 on: May 05, 2017, 09:28:07 pm »
 Ah, I see. Thats fine  :)

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus