Logarithmic Axis -> dB Axis

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
drizzzel
Posts: 7
Joined: Wed Aug 27, 2008 9:08 pm

Logarithmic Axis -> dB Axis

Post by drizzzel » Fri Sep 26, 2008 6:25 pm

Hi All,
I am trying to create an axis which is somewhat of a hybrid of a regular, linear Number Axis and a Logarithmic Axis. I would like to display my data in terms of dB, or 10*log(value) that I am plotting. I found it trivial to convert the Logarithmic Axis to this purpose, but the problem is that I need the axis itself to be displayed linearly.

I have decided to start with NumberAxis and create my own new axis based on that class. I added a method to convert a given value to 10*log(value), and I have implemented this method within the new class in a similar fashion to how it is done in LogarithmicAxis. In particular, I have modified the following methods:

Code: Select all

valueToJava2D

Code: Select all

java2DToValue

Code: Select all

refreshTicksHorizontal

Code: Select all

refreshTicksVertical
so that wherever a call is made to fetch a range value, or a data value, it is converted to the 10*log(value) prior to proceeding through the method. This is what I see as similar to how it's done in the LogarithmicAxis class.

When I put the axis into my program, it renders the plot blank, so I am guessing that I am missing something, or not fully understanding how these axis classes truly work.

I think it's easier to start with NumberAxis rather than LogarithmicAxis, as then I don't have to worry about all the extra futzing around with powers and tick mark locations, I just want a linear scale, but I want to convert all my data to 10Log(val)... Applying the conversion pre-plot is not really an attractive option.

Does anyone have any hints or suggestions? Has anyone tried to do this before?

Thanks,
d

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Thu Oct 02, 2008 9:22 am

My guess would be that the problem lies in the autoAdjustRange() method which will still be working with the "raw" data values, rather than the adjusted "10*log(value)" figures.

Any chance you could post a small sample dataset so I can better understand the transformation that the axis needs to do?
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

drizzzel
Posts: 7
Joined: Wed Aug 27, 2008 9:08 pm

Post by drizzzel » Thu Oct 02, 2008 4:39 pm

Hi Dave,
Thanks for the reply... I'll take a look at that method today and see if I can spot the problem... If I can't get it to work, I'll post a dataset.

Cheers,
dave

drizzzel
Posts: 7
Joined: Wed Aug 27, 2008 9:08 pm

Post by drizzzel » Tue Oct 07, 2008 6:29 pm

Busy week, but managed to find some time yesterday to look at this problem again...

I was able to get the java2DToValue and valueToJava2D methods to work properly. Along with the autoAdjustRange methods. So the data are now displayed on the screen properly. To achieve this with minimum impact on the rest of the class, I wrote 2 mehods:

Code: Select all

    protected double reverseCalcLog10( double val ) {
	return Math.exp( val / 10.0 * LOG10 );
    }

    protected double calcLog10( double val ) {
	return 10.0d * ( Math.log( val ) / LOG10 );
    }
These methods are called whenever the class needs to manipulate a value. They essentially fool the axis into thinking that it is dealing with the dB value ( 10*Log(value) )rather than the actual value. For example, I call the method calcLog10(value) whenever the class has called getRange() and convert the values prior to the code doing anything with those values. This all seems to work now, including allowing me to place range markers on the plot in the proper locations.

However, I still cannot get the ticks to display properly. I am having a hard time understanding why it is that if the default tick unit size is set to 1.0, that at some point, it is set automatically to 1.0E-7 prior to the plot being displayed. The causes the number of ticks to be ridiculously large, and then no ticks get displayed.

To give some perspective, the data I am testing has a range value of approximately Range = [0.000123, 0.009] (on the Y-axis - the axis in question). When translated to dB, this data range is from [-39.1, -10.5] (roughly). refreshTickVertical is calculating my lowest tick value properly ( it gives me -39.05 ) however, despite the DEFAULT_TICK_UNIT being set to 1.0 at the top of the class, in the calculateVisibleTickCount method, the TickUnit is returned at 1.0E-7??? This causes the number of ticks to be high, and I'm assuming that this is why they are not drawn. :?:

Another thing I tried was setting the tickUnit when I instantiate the Axis by using the following code:

Code: Select all

	magLogAxis = new DbAxis( "Amplitude [dB]" );
	magLogAxis.setAutoRange( true );
	magLogAxis.setAutoRangeIncludesZero( false );
	magLogAxis.setUpperMargin( 0.05 );
	magLogAxis.setLowerMargin( 0.05 );
	magLogAxis.setTickUnit( new NumberTickUnit( 1.0 ) );
By doing this, the tickUnit does indeed start off at 1.0 (overriding the presumed default of 1.0E-7) and the tickLabelSize seems to be affected, because the plot now draws the Axis label away from the edge of the plot (seemingly leaving room for tick labels). But there are no lables or ticks drawn beside the plot. Instead, they are drawn all on top of one another in the upper left corner of my plot panel. ??? This seems to be perhaps a symptom of a different problem...

Anyhow, I'm continuing to work on the problem, but would really appreciate any advice or tips anyone can throw at me. I am confident that I am likely missing some very minute detail that will solve my problem.

I am happy to share this class (once it works) to anyone needing to display data easily with a dB axis.

Cheers,
dave

drizzzel
Posts: 7
Joined: Wed Aug 27, 2008 9:08 pm

Post by drizzzel » Thu Oct 09, 2008 7:50 pm

Pleased to report that I finally got this working. I had to abandon the direction I had started with, and discovered that it was simpler to actually delve into the LogarithmicAxis code. By making modifications to the class wherever a calculation was made ( ie. Math.log( value ) or Math.pow( 10, value) ) into the correct conversion to dB, and also by making extensive changes to the refreshTicksVertical and refreshTicksHorizontal (although not sure a Horizontal dB axis would ever be useful).

If anyone could make use of this axis, please let me know.

Cheers,
dave

dan_
Posts: 2
Joined: Tue Nov 18, 2008 1:40 am

Post by dan_ » Tue Nov 18, 2008 1:43 am

Dave, I would like to have a copy of your axis. It sounds exactly like what I need to replace another set chart controls. Thanks.

drizzzel
Posts: 7
Joined: Wed Aug 27, 2008 9:08 pm

Post by drizzzel » Tue Nov 18, 2008 7:54 am

Hi Dan,
I see that pm's have been disabled on this board. If you can somehow get me your email address, I'll send you a copy of the class... There are too many widespread changes to list.

d

dan_
Posts: 2
Joined: Tue Nov 18, 2008 1:40 am

Post by dan_ » Tue Nov 18, 2008 6:36 pm

Dave, you can send it to:

danQQ1975@live.com

(remove the QQ)

Thanks.

matinh
Posts: 483
Joined: Fri Aug 11, 2006 10:08 am
Location: Austria

Post by matinh » Tue Nov 18, 2008 6:48 pm

How about posting the code here or at JFreeChart's Sourceforge page as an enhancement? This way it would eventually make it into JFreeChart one day.

thx,
- martin

Locked