Recent

Author Topic: Axis transformation to show a different unit  (Read 2590 times)

ironphil

  • New Member
  • *
  • Posts: 48
Axis transformation to show a different unit
« on: June 25, 2015, 08:14:10 pm »
I want to be able to show my data using different units. I am trying to create a second horizontal axis, using axis transformation, to show the other unit. All the source data and the data manipulation are done with the original X unit and I do not want to change that, I just want to show the same data using a different unit.
The relation between the two units is simple: 2nd unit = 12.398 / 1st unit (relation between energy (keV) and wavelength (A) of electrons).
I almost managed to do it using UserDefinedAxisTransform but the labels are not spaced regularly and are disappearing when I zoom in.
I have these two procedures:
Code: [Select]
procedure TForm1.ChartAxisTransformations1UserDefinedAxisTransform1AxisToGraph(
  AX: Double; out AT: Double);
begin
  if AX < 0.001 then exit;
  AT:= 12.398 / AX;
end;

procedure TForm1.ChartAxisTransformations1UserDefinedAxisTransform1GraphToAxis(
  AX: Double; out AT: Double);
begin
  if AX < 0.001 then exit;
  AT:= 12.398 / AX;
end;
The "if AX < 0.001" is to prevent very large values when it gets close to 0 on one of the axis. I have values down to 0 on the original axis but I do not need to transform them, down to 0.001 is enough. The second unit should never get close to 0 so it should not be a problem.

Any idea how to successfully achieve this?

wp

  • Hero Member
  • *****
  • Posts: 6301
Re: Axis transformation to show a different unit
« Reply #1 on: June 25, 2015, 11:03:09 pm »
Could you post a little project which I can use to play with?
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

wp

  • Hero Member
  • *****
  • Posts: 6301
Re: Axis transformation to show a different unit
« Reply #2 on: June 26, 2015, 12:11:38 pm »
I am attaching two demo projects which maybe cover your issue

Both projects use the same data, an imaginary measurement of some quantity Y (=1/E) as a function of electron energy E.

In project1, I plot Y as a function of E and add a top axis showing the wavelengths to each E value. This is achieved by means of a handler for the top axis' OnMarkToText event.

In project2, the measured E values are converted to wavelengths which are used as x coordinates for plotting. This is achieved by means of a UserDefinedAxisTransformation. Again there is a top axis displaying the corresponding energy values. When using an AxisTransform make sure to select the axes to which the series is linked.

Note that axis label calculation in the current version of TAChart gets screwed up by an axis transform which flips the axis minimum and maximum. I just uploaded a corrected version. Please use Lazarus trunk for proper operation of project2. Or copy the files TAChartAxis.pas and TAIntervalSource.pas from http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/components/tachart/?root=lazarus to the TAChart folder of your Lazarus installation and recompile the TAChart package (make a backup copy first!).
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

ironphil

  • New Member
  • *
  • Posts: 48
Re: Axis transformation to show a different unit
« Reply #3 on: June 26, 2015, 03:53:05 pm »
I have attached my test project so far. I think it is not working because of what you found with your project2. But your project1 appears to do the job perfectly without using the axis transformation, I think I will use that approach.
I need to upgrade to trunk for project2, I am getting an "External: SIGFPE" right now. I will try to implement your project1 approach into my main application and let you know if it works. Thank you very much for your time.

wp

  • Hero Member
  • *****
  • Posts: 6301
Re: Axis transformation to show a different unit
« Reply #4 on: June 26, 2015, 08:47:34 pm »
Quote
I am getting an "External: SIGFPE" right now
Maybe my advice to replace the two files was too aggressive - I see in the svn log that probably there was another change in the TAChartAxis file which could screw up your installation.

Are you using Laz 1.4? If yes, restore the original TAChartAxis.pas. Open it in Lazarus. Scroll down to TChartAxis.GetMarkvalues. Add "EnsureOrder(FValueMin, FValueMax);" and "EnsureOrder(FMinForMarks, FMaxForMarks);" to the end of the "with FHelper..." block near the end of the procedure.

There were no changes to TAIntervalSource after Laz 1.4.

Recompile the TAChart package; if you still get an error perform a clean recompilation of Lazarus.

The best solution, of course, is to switch to trunk completely.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10