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.
Update: Pushed improved version to Incanter.
This is how our final code will look like:
And this is the supporting code:
Admittedly, this is a little overengineered with the multimethod, but there were reasons for it :-).
Update: Pushed improved version to Incanter.
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. :x 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 :x (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 (= :x dimension)
(.setDomainAxis plot axis)
(.setRangeAxis plot axis)))
chart))
Admittedly, this is a little overengineered with the multimethod, but there were reasons for it :-).