2021-04-21 11:38:28 +00:00
#+title : Org mode: Babel
2021-04-01 16:08:15 +00:00
#+date : "2020-04-17 21:41:30 +08:00"
2021-04-21 11:38:28 +00:00
#+date_modified : "2021-04-21 17:43:52 +08:00"
2021-04-01 16:08:15 +00:00
#+language : en
#+properties : header-args :session :exports both
2021-04-05 12:03:26 +00:00
#+tags : research.reproducibility
2020-06-23 18:29:05 +00:00
2021-04-21 11:38:28 +00:00
Org-babel is the framework that enables [[file:2020-04-20-16-51-40.org ][Org mode ]] to insert output of the code from programming languages.
It is also the one thing that makes Org mode to be used as a tool for [[file:2020-04-12-11-20-53.org ][Reproducible research ]].
2020-06-23 18:29:05 +00:00
As of 2020-06-08, [[https://orgmode.org/worg/org-contrib/babel/languages.html ][Babel supports more than 50 languages ]] with the possibility of adding of other languages that are not supported yet.
* The fundamental concepts
Here's an example of a code block executed with the shell.
2021-04-01 16:08:15 +00:00
#+begin_src sh
2020-06-23 18:29:05 +00:00
echo "HELLO WORLD"
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2020-06-23 18:29:05 +00:00
: HELLO WORLD
To execute the code block, simply run ~org-babel-execute-src-block~ (by default, this is mapped in ~<C-c> <C-c>~ ).
The results will be printed into a result block.
Each of the supported language may also have an exclusive option with each language suitable for certain processes.
2021-04-21 11:38:28 +00:00
For example, with Python 3, you can pretty print it in accordance to Org mode display.
2020-06-23 18:29:05 +00:00
An array will create a table, for instance with ~:results value~ [[https://orgmode.org/manual/Using-Header-Arguments.html#Using-Header-Arguments ][header argument ]].
2021-04-01 16:08:15 +00:00
#+begin_src python :results value
2020-06-23 18:29:05 +00:00
[["Item", "Value"], ["Baseball bat", 123], ["Baseball glove", 25], ["Printed shirt", 42]]
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2020-07-06 15:32:10 +00:00
: None
2020-06-23 18:29:05 +00:00
You can also export graphics with tools such as [[http://gnuplot.info/ ][Gnuplot ]], [[https://www.gnu.org/software/octave/ ][GNU Octave ]], [[https://www.r-project.org/ ][R ]], and even [[https://www.latex-project.org/ ][LaTeX ]].
2020-07-06 15:32:10 +00:00
With it, you can export the graphics into a file (commonly with ~:file <PATH>~ ).
2020-06-23 18:29:05 +00:00
2021-04-15 13:18:44 +00:00
#+begin_src gnuplot :exports both :file assets/2020-04-17-21-41-30/gnuplot-demo.png
2020-06-23 18:29:05 +00:00
unset arrow
unset label
set grid
splot x**2+y* *2, x* *2-y* *2
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2021-04-15 13:18:44 +00:00
[[file:assets/2020-04-17-21-41-30/gnuplot-demo.png ]]
2020-06-23 18:29:05 +00:00
With Org-babel, you can share either the output, the code used to generate the output, or both.
This is commonly set with the ~:exports~ header argument.
[fn:: Again, this varies whether export options are available for each Babel-supported lanaguages.]
Here's an example where I decided to show only the output with ~:exports results~ .
2021-04-15 13:18:44 +00:00
#+begin_src gnuplot :exports results :file assets/2020-04-17-21-41-30/gnuplot-3d-demo.png
2020-06-23 18:29:05 +00:00
set title "3D gnuplot demo"
unset grid
splot x*y with points
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2021-04-15 13:18:44 +00:00
[[file:assets/2020-04-17-21-41-30/gnuplot-3d-demo.png ]]
2020-06-23 18:29:05 +00:00
* Sessions
2020-07-06 15:32:10 +00:00
Each of the source code block runs on an individual session.
However, you can connect source code blocks (with the supported languages) in the same session with ~:session <SESSION NAME>~ .
2020-06-23 18:29:05 +00:00
Let's start with a simple example where we want to demonstrate some Python shenanigans.
Here's one Python code block.
2021-04-01 16:08:15 +00:00
#+begin_src python :results output :session python-example
2020-06-23 18:29:05 +00:00
x = 35
print(x)
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2020-06-23 18:29:05 +00:00
: 35
2020-07-06 15:32:10 +00:00
Then here's another code block in the same session.
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+begin_src python :results output :session python-example
2020-06-23 18:29:05 +00:00
for i in range(5):
x += 5
print(x)
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2020-06-23 18:29:05 +00:00
: 40
: 45
: 50
: 55
: 60
In certain code where the output can still change (for example, try executing the previous code block again), this may not be the desired behavior.
To correct this, simply execute ~org-babel-execute-buffer~ .
2020-07-06 15:32:10 +00:00
2020-06-23 18:29:05 +00:00
* Integrating between different programming languages
2021-04-21 11:38:28 +00:00
You can also pass Org mode variables (from ~#+NAME: <VAR>~ ) [fn: : Technically called an internal link (https://orgmode.org/org.html#Internal-Links). ] into the source code blocks with the ~:var <NAMEC>=<DATA>~ (though, this may vary among Babel runtimes).
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+name : example_string
2020-06-23 18:29:05 +00:00
This is the string.
2021-04-01 16:08:15 +00:00
#+begin_src python :var example=example_string :results value
2020-06-23 18:29:05 +00:00
example
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2020-07-06 15:32:10 +00:00
: None
2020-06-23 18:29:05 +00:00
This is the source code from the document, for reference.
2021-04-01 16:08:15 +00:00
#+begin_src org :exports code :results silent
2020-06-23 18:29:05 +00:00
,#+NAME: example_string
This is the string.
,#+BEGIN_SRC python :var example=example_string :outputs value
example
,#+END_SRC
,#+RESULTS:
,: This is the string.
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-21 11:38:28 +00:00
Org mode variables does capture an element as its input.
2020-06-23 18:29:05 +00:00
This has a lot of implications of passing data between different sessions and even different languages.
For example, we could still capture the ~x~ variable from the previous Python code blocks.
2021-04-01 16:08:15 +00:00
#+name : var_from_other_lang
#+begin_src python :results silent :session python-example :exports value
2020-06-23 18:29:05 +00:00
x # Which should be 60 at this point.
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-21 11:38:28 +00:00
Then, pass it to some other Org mode blocks with the variable.
2020-06-23 18:29:05 +00:00
(Since the captured variable are always going to be a string, we have to convert it into the appropriate type.)
2021-04-01 16:08:15 +00:00
#+begin_src R :results output :var python_var=var_from_other_lang
2020-06-23 18:29:05 +00:00
as.numeric(python_var) + 2
2021-04-01 16:08:15 +00:00
#+end_src
2020-06-23 18:29:05 +00:00
2021-04-01 16:08:15 +00:00
#+results :
2020-06-23 18:29:05 +00:00
: [1] 62