Clojure Plotting to Org inline image in ob-clojure
1. The Process of my Clojure Plotting
ID: ea7fb5d6-b228-450f-8bb2-502cd5020404 PUBDATE: <2019-08-14 Wed 19:08>
1.1. ask whether Clojure/JVM can change working directory
ID: c63620be-3661-443f-9251-faa7d4e3666d
I did some hard search, found some links
- https://stackoverflow.com/questions/840190/changing-the-current-working-directory-in-java
- https://stackoverflow.com/questions/19008592/java-change-file-working-directory
Then I found JVM does not allow to change working directory because of security reason https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4045688.
So, there is no reliable way to do this in pure Java. Setting the user.dir
property via System.setProperty()
or java -Duser.dir=...
does seem to affect
subsequent creations of Files, but not e.g. FileOutputStreams
.
1.2. I create Org-mode library "ob-clojure-literate
" and improve Org Babel "ob-core.el
" for plotting support
ID: 0720a1e8-a039-48e5-8d49-c174b9f4cf64
Because changing Clojure/JVM working directory is not available, so I find
method on Emacs side, Org-mode other Babel lanaguages like R, Python have good
image file result support. So I dive into source code, and try to add similar
function to "ob-clojure
". But I found some limites, then I created
"ob-clojure-literate (GitHub repo)" (Now it is in
Org-mode
contrib lib).
1.3. use more better solution by passing target path into Clojure with header argument :var
ID: cc6d0973-7a2a-4dfd-aa09-511142b0692c
You can fake change Clojure REPL working directory by passing header argument variable into Clojure code. Like this:
#+begin_src clojure :results value :var dir=(concat (file-name-directory (buffer-file-name)) "data/images/")
(str dir "ob-clojure-literate.png")
#+end_src
#+RESULTS[<2018-05-17 01:12:55> 73be0ca9a40a4f1e4fdee8e535991955f77b034a]:
: "/home/stardiviner/Org/Wiki/Computer Technology/Programming/Emacs/data/Emacs Packages/Org mode/data/images/ob-clojure-literate.png"
Then you can use Clojure funciton to save graphics object to target file with correct absolute path:
#+HEADERS: :var cwd=(concat (file-name-directory (buffer-file-name)) "data/images/")
#+begin_src clojure :results graphics file link :dir "data/images" :file "ob-clojure-literate.png"
(use '(incanter core stats datasets charts io pdf))
(def hist (histogram (sample-normal 1000)))
(save hist (str cwd "ob-clojure-literate.png"))
#+end_src
(use '(incanter core stats datasets charts io pdf))
(def hist (histogram (sample-normal 1000)))
(save hist (str cwd "ob-clojure-literate.png"))
1.4. use final solution by move image file to target path with Clojure function
ID: ac0e66d2-e034-45d4-907c-d10a0d413ff2
#+begin_src clojure :results graphics file link :dir "data/images" :file "ob-clojure-incanter-move.png" :var dir=(concat (file-name-directory (buffer-file-name)) "data/images/")
(use '(incanter core stats datasets charts io pdf))
(import '(java.io File))
(def hist (histogram (sample-normal 1000)))
(save hist "ob-clojure-incanter-move.png")
(.renameTo (File. "ob-clojure-incanter-move.png") (File. (str dir "ob-clojure-incanter-move.png")))
#+end_src
(use '(incanter core stats datasets charts io pdf))
(import '(java.io File))
(def hist (histogram (sample-normal 1000)))
(save hist "ob-clojure-incanter-move.png")
(.renameTo (File. "ob-clojure-incanter-move.png") (File. (str dir "ob-clojure-incanter-move.png")))
2. Incanter
ID: 147a25a2-ea60-4b37-ae1d-d5a58872908b PUBDATE: <2019-08-14 Wed 19:08>
#+begin_src clojure :results graphics :dir "data/images" :file "ob-clojure-literate.png" :var dir=(concat (file-name-directory (buffer-file-name)) "data/images/")
(use '(incanter core stats datasets charts io pdf))
(def hist (histogram (sample-normal 1000)))
(save hist (str dir "ob-clojure-literate.png"))
#+end_src
(use '(incanter core stats datasets charts io pdf))
(def hist (histogram (sample-normal 1000)))
(save hist (str dir "ob-clojure-literate.png"))
3. clj-xchart
ID: 75039b3a-a2ef-40b8-89fa-2522728deb59 PUBDATE: <2019-08-14 Wed 19:08>
#+begin_src clojure :results graphics file link :dir "data/images" :file "ob-clojure-clj-xchart.png" :var dir=(concat (file-name-directory (buffer-file-name)) "data/images/")
(require '[com.hypirion.clj-xchart :as xchart])
(def ob-clojure-clj-xchart
(xchart/xy-chart {"Expected rate" [(range 10) (range 10)]
"Actual rate" [(range 10) (map #(+ % (rand-int 5) -2) (range 10))]}))
;; (xchart/view ob-clojure-clj-xchart)
(xchart/spit ob-clojure-clj-xchart (str dir "ob-clojure-clj-xchart.png"))
#+end_src
(require '[com.hypirion.clj-xchart :as xchart])
(def ob-clojure-clj-xchart
(xchart/xy-chart {"Expected rate" [(range 10) (range 10)]
"Actual rate" [(range 10) (map #(+ % (rand-int 5) -2) (range 10))]}))
;; (xchart/view ob-clojure-clj-xchart)
(xchart/spit ob-clojure-clj-xchart (str dir "ob-clojure-clj-xchart.png"))
4. ggplot2
ID: 1e093992-48d3-4936-888b-8f1d229ae1d2 PUBDATE: <2019-08-14 Wed 19:08>
5. jutsu
ID: bda68b36-d3ee-4e74-899b-187837ceaac0 PUBDATE: <2019-08-14 Wed 19:08>
6. References
ID: 86190f87-a4d6-4364-8b7b-560b13252e4f PUBDATE: <2019-08-14 Wed 19:08>
I also posted this method on Org Mode Worg documentations: https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-clojure.html
7. Make use of CIDER new support of image content-type
ID: 20bedc46-cea4-488b-ba17-d46552ea513d PUBDATE: <2019-08-14 Wed 19:08>
Since the PR https://github.com/clojure-emacs/cider-nrepl/pull/517 got merged into CIDER. It is realsed in CIDER 0.17 (Andalucía).
CIDER in Emacs can handle various image content-types now and render image in the REPL.
I'm considering how to integrate this feature into ob-clojure.el
to save image
content-type as file.
8. Literaral Org-mode version
ID: 57506a9a-3534-40ca-aef2-59b12d66fdc8 PUBDATE: <2019-08-14 Wed 19:08>
If you want to see Literal Org-mode version of this post, click the "Show Org Source" button!