
Hello,
I'm trying to put together a little tool for displaying audio measurements. Such plots do usually have two logarithmic axes, though the amplitude axis is scaled linear by using dB.
The frequency axis, however, should be scaled logarithmic and has to cover approximately the human range of audibility from 20 Hz to 20 kHz. If I set up a plot using a logarithmic oxyPlot, I get something like this:
I would like to have more displayed Steps (frequency labels) on the frequency axis, like this:
Obviously, I can't just adjust the Axis' Base, as I would get rather odd numbers. Is there any way to achieve such an axis labeling with oxyPlot?
Thanks in advance



I don't think it's possible right now. You should modify the GetTickValues method inside the LogarithmicAxis.cs file (particularly majorTickValues list). Please post the solution if you find out how to do it. Good luck.



If you're not bothered about the minor ticks being the same size as major ticks then this is a bit of a hacky way to do this. Just change the minor ticks to major ticks.
Inside LogarithmicAxis.cs, GetTickValues()....
if (d2 >= this.ActualMinimum && d2 <= this.ActualMaximum)
{
//minorTickValues.Add(d2);
majorTickValues.Add(d2);
}


Aug 11, 2013 at 3:20 PM
Edited Aug 14, 2013 at 8:00 AM

Hello there,
it's been a while... Finally got to work on this.
everytimer: Thanks for pointing me in the right direction!
Main differences between my implementation and original (assuming base=10, but works with any other base):
You can zoom out and display many decades without messing up the labels
A Decade is subdivided if there's enough space for the labels
The IntervalLength property is actually used by the algorithm
Example:
For several reasons, I did my fix in the form of a simple override.
In case anyone's interested and not bothered by a little VB:
Imports System.Math
Public Class MyLogAxis
Inherits Axes.LogarithmicAxis
Public Overrides Sub GetTickValues(ByRef majorLabelValues As IList(Of Double), ByRef majorTickValues As IList(Of Double), ByRef minorTickValues As IList(Of Double))
majorTickValues = New List(Of Double)
minorTickValues = New List(Of Double)
Dim screensize As Integer
If Me.IsHorizontal Then
screensize = Me.ScreenMax.X  Me.ScreenMin.X
Else
screensize = Me.ScreenMax.Y  Me.ScreenMin.Y
End If
Dim totalBW As Double = Log(Me.ActualMaximum, Me.Base)  Log(Me.ActualMinimum, Me.Base)
Dim BWratio As Double = width / totalBW
If totalBW < 1 Then
MyBase.GetTickValues(majorLabelValues, majorTickValues, minorTickValues)
ElseIf BWratio < Me.IntervalLength Then
Dim steps As Integer = Ceiling(Me.IntervalLength / BWratio)
Dim c As Double = Ceiling(Log(Me.ActualMinimum, Me.Base))
While c < Floor(Log(Me.ActualMaximum, Me.Base))
minorTickValues.Add(Round(Pow(Me.Base, c), 10))
If c Mod steps = 0 Then
majorTickValues.Add(Round(Pow(Me.Base, c), 10))
End If
c += 1
End While
Else
Dim c As Double = Floor(Log(Me.ActualMinimum, Me.Base))
Dim v As Double
Dim c2 As Double
Dim lower As Double
While c < Ceiling(Log(Me.ActualMaximum, Me.Base)) + 1
v = Pow(Me.Base, c)
If v > Me.ActualMinimum And v < Me.ActualMaximum Then
majorTickValues.Add(Round(v, 10))
End If
Dim a As Integer = 1
lower = c
While a < Me.Base
c2 = c + Log(a, Me.Base)
v = Pow(Me.Base, c2)
If v + 0.00001 >= Me.ActualMinimum And v <= Me.ActualMaximum + 0.00001 Then
minorTickValues.Add(Round(Pow(Me.Base, c2), 10))
If BWratio * Min(c2  lower, c + 1  c2) > Me.IntervalLength Then
majorTickValues.Add(Round(v, 10))
lower = c2
End If
End If
a += 1
End While
c += 1
End While
End If
majorLabelValues = majorTickValues
End Sub
End Class



Great stuff, and good looking graph =)

