Creating A Chart With A Logarithmic Axis In Incanter 1.5.1

Incanter 1.5.1 doesn’t support logarithmic axes, fortunately it is easy to add one manually.

This is how our final code will look like:

;; core and charts are the incanter namespaces
(defn plot-power []
(let [fun #(Math/pow 10 %)
y-axis (log-axis :label "log(x)")
chart (charts/function-plot fun 0 5)]
(set-axis chart :y y-axis)
(core/view chart :window-title "LogAxis Test: Incanter fun plot")))

And this is the supporting code:

(defn log-axis
" Create a logarithmic axis.

Beware: The data may not contain zero. Otherwise the chart will look
rather strange (log doesn't like zeros).

Options: :base (default 10) base of the logarithm; typically 2 or 10
:label (default none) the label of the axis
"
[& options]
(let [opts (when options (apply assoc {} options))
base (or (:base opts) 10)
label (:label opts)]
(doto (if label
(LogAxis. label)
(LogAxis.))
(.setBase base)
;; Use normal numbers instead of 10^num, i.e. 1 inst. of 10^0.0
(.setStandardTickUnits (NumberAxis/createIntegerTickUnits)))))

(defmulti set-axis
"Set the selected axis of the chart, returning the chart.
(Beware: the axis' label will replace the x-label or y-label set previously on the chart.)

Arguments:
chart - the JFreeChart object whose axis to change
dimension - depends on the plot type, f.ex. 😡 or :y for an XYPlot
axis - the axis to set, an instance of ValueAxis

Examples: (use '(incanter core charts))

(doto (function-plot #(Math/pow 10 %) 0 5) (set-axis 😡 (log-axis
:base 10, :label \"log(x)\")) view)
"

(fn [chart dimension axis] (type (.getPlot chart))))

(defmethod set-axis org.jfree.chart.plot.XYPlot
([chart dimension axis]
{:pre [(#{:x :y} dimension)]}
(let [plot (.getXYPlot chart)]
(if (= 😡 dimension)
(.setDomainAxis plot axis)
(.setRangeAxis plot axis)))
chart))

Admittedly, this is a little overengineered with the multimethod, but there were reasons for it :-).