Skip to content

Latest commit

 

History

History
287 lines (237 loc) · 9.13 KB

clj-plot.org

File metadata and controls

287 lines (237 loc) · 9.13 KB

Spacemacs Org-mode and Clojure

Spacemacs Org-mode and Clojure

This is going to be examples of how clojure could be used from org-mode

Prerequisites

Spacemacs

Install Spacemacs from develop branch. Add desired org babel languages to .spacemacs file in dotspacemacs/user-config section List of supported languages is here

(with-eval-after-load 'org
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((clojure . t))))

Clojure

Detailed installation instruction are here

Code execution

Create deps.edn file with dependencies

echo "{}" >> deps.edn

In case of example there are no dependencies so that empty clojure map is printed out to deps.edn

Create example org file for experiments:

touch example.org

Now we can write some code:

Elementary results

;; #+begin_src clojure :results pp
(defn power [n x]
  (reduce * (repeat x n)))
(power 2 3)
;; #+end_src
8

Results as table

List of lists - generate multiplication table

;; #+begin_src clojure :results value
(let [from  1
      to    8
      mults (for [x (range from to)
                  y (range from to)]
              (* x y))
      table (partition (- to from) mults)]
  (list* (first table)
         'hline
         (rest table)))
1234567
2468101214
36912151821
481216202428
5101520253035
6121824303642
7142128354249

Vector of maps

;; #+begin_src clojure :results value table
[{:user/name "Bob"
  :user/level :d1
  :note "order # 1"}
 {:user/name "Sara"
  :user/level :l1
  :note "order # 2"}]
;; #+end_src
:user/nameBob:user/level:d1:noteorder # 1
:user/nameSara:user/level:l1:noteorder # 2

Print raw clojure’s pprint table

;; #+begin_src clojure :results value pp
(clojure.pprint/print-table 
 [{:user/name "Bob"
   :user/level :d1
   :note "order # 1"}
  {:user/name "Sara"
   :user/level :l1
   :note "order # 2"}])
;; #+end_src
| :user/name | :user/level |     :note |
|------------+-------------+-----------|
|        Bob |         :d1 | order # 1 |
|       Sara |         :l1 | order # 2 |

Create out own print-org-table helper function

(defn print-org-table
  ([rows] 
   (print-org-table (keys (first rows)) rows))
  ([ks rows]
   (list* ks 'hline
          (map #(for [k ks] (get % k)) rows))))
;; #+begin_src clojure :results value table
(print-org-table [{:user/name "Bob"
                   :user/level :d1
                   :note "order # 1"}
                  {:user/name "Sara"
                   :user/level :l1
                   :note "order # 2"}])
;; #+end_src
:user/name:user/level:note
Bob:d1order # 1
Sara:l1order # 2

List your results

;; #+begin_src clojure :results value list
{:user/name "Bob"
 :user/level :d1
 :note "order # 1"}
;;#+end_src
  • :user/name
  • Bob
  • :user/level
  • :d1
  • :note
  • order # 1

Working with tables

Plotting

Is this possible to reproduce the case, described in this article ? And add Vega charts to list of demos.

Incanter

(use '(incanter core stats datasets charts io))
(def hist (histogram (sample-normal 10000)))
(save hist "./images/incanter.png")

images/incanter.png

XCharts

(require '[com.hypirion.clj-xchart :as c])
(def chart (c/xy-chart
            {"Memory usage" {:x     (range 0 10 0.5)
                             :y     [0.0 0.5 2.3 4.5 2.7 4.5 6.7
                                     9.0 9.3 9.5 6.7 7.5 8.8 10.3
                                     9.7 11.4 5.6 4.5 5.6 1.2]
                             :style {:marker-type :none}}
             "Total memory" {:x     [-100 100]
                             :y     [12 12]
                             :style {:render-style :line
                                     :marker-type  :none
                                     :line-color   :red}}}
            {:title        "Memory usage"
             :render-style :area
             :x-axis       {:title "Time (min)"
                            :min   0
                            :max   10}
             :y-axis       {:title "Memory (GB)"
                            :max   15}
             :legend       {:position :inside-nw}}))

;; (c/view chart)
(c/spit chart "./images/xchart.png")

images/xchart.png

Gnuplots

  • brew install gnuplots
(require '[gnuplot.core :as g])

(g/raw-plot!
 [[:set :title "simple-test" :font ",40"]
  [:set :style :textbox :opaque :noborder]
  [:set :boxwidth 1 :abs]
  [:set :term :png]
  [:set :output "./images/gnuplot.png"]
  [:plot
   (g/range :* :*)
   (g/list ["-" :title "rising" :with :filledcurve :x1]
           ["-" :title "falling" :with :boxes])]]
 [[[0 0] [1 1] [2 1.5]
   [3 1] [4 6] [5 4]]
  [[0 5] [1 4] [2 3]
   [3 2] [4 1] [5 0]]])

images/gnuplot.png

Vega, Vega lite wrappers

Oz can view but not possible yet to export to svg programmatically However vega-cli tools could be used to convert Vega spec to any format

  • install vega globally npm i -g vega-cli
  • install vega-lite globally npm i -g vega-lite
(require '[clojure.java.shell :as sh])
(require '[clojure.data.json :as json])

(defn temp-json-file
  "helper function convert clj vega spec to json and store it as tmp file"
  [content]
  (let [tmp-file (java.io.File/createTempFile "vega." ".json")]
    (.deleteOnExit tmp-file)
    (with-open [file (clojure.java.io/writer tmp-file)]
      (json/write content file))
    (.getAbsolutePath tmp-file)))

(defn play-data [& names]
  (for [n names
        i (range 200)]
    {:time     i
     :item     n
     :quantity (+ (Math/pow (* i (count n)) 0.8) (rand-int (count n)))}))

(def line-plot
  {:data     {:values (play-data "monkey" "slipper" "broom")}
   :encoding {:x     {:field "time" :type "ordinal"}
              :y     {:field "quantity" :type "quantitative"}
              :color {:field "item" :type "nominal"}}
   :width    400
   :height   400
   :mark     "line"})

(sh/sh "vl2png" (temp-json-file line-plot) "./images/vega.png")

images/vega.png

Yes it is very possible!

[TBD]