#+OPTIONS: H:3 num:nil toc:2 \n:nil ::t |:t ^:{} -:t f:t *:t tex:t d:(HIDE) tags:not-in-toc
#+STARTUP: align fold nodlcheck hidestars oddeven lognotestate hideblocks
#+SEQ_TODO: TODO(t) INPROGRESS(i) WAITING(w@) | DONE(d) CANCELED(c@)
#+TAGS: Write(w) Update(u) Fix(f) Check(c) noexport(n)
#+TITLE: Maxima Source Code Blocks in Org Mode
#+AUTHOR: Thomas S. Dye
#+EMAIL: tsd[at]tsdye[dot]com
#+LANGUAGE: en
#+HTML_LINK_UP: index.html
#+HTML_LINK_HOME: https://orgmode.org/worg/
#+EXCLUDE_TAGS: noexport
#+PROPERTY: header-args:org :exports code :results replace
#+name: banner
#+begin_export html
#+end_export
#+name: ob-doc-maxima-requires-ob-org
#+begin_src elisp :exports none :results silent
(require 'ob-org)
#+end_src
* Template Checklist [9/12] :noexport:
- [X] Revise #+TITLE:
- [X] Indicate #+AUTHOR:
- [X] Add #+EMAIL:
- [X] Revise banner source block [3/3]
- [X] Add link to a useful language web site
- [X] Replace "Language" with language name
- [X] Find a suitable graphic and use it to link to the language
web site
- [X] Write an [[Introduction]]
- [X] Describe [[Requirements and Setup][Requirements and Setup]]
- [X] Replace "Language" with language name in [[Org Mode Features for Language Source Code Blocks][Org Mode Features for Language Source Code Blocks]]
- [X] Describe [[Header Arguments][Header Arguments]]
- [ ] Describe support for [[Sessions]]
- [ ] Describe [[Result Types][Result Types]]
- [ ] Describe [[Other]] differences from supported languages
- [X] Provide brief [[Examples of Use][Examples of Use]]
* Introduction
Maxima is a computer algebra system descended from Macsyma, which was
originally released in 1982. It is released under the terms of the
GNU General Public License.
Maxima is written in Common Lisp. It can be accessed and extended in
Lisp.
* Requirements and Setup
Maxima binaries are available for Windows and Linux. These either
require a compatible Common Lisp or an executable Lisp image. Mac OS
X users can install via brew or MacPorts. The combinations of
operating system and Lisp implementation known to run Maxima can be
found on [[http://maxima-project.org/wiki/index.php?title%3DMaxima_ports][the Maxima ports page]].
There are several versions of Maxima, some with different names. The
variable =org-babel-maxima-command= can be set to the name of your
Maxima executable. The default value is "maxima".
Maxima ships with =Emacs= modes. Instructions for configuring them
can be found on [[http://emacswiki.org/emacs/MaximaMode][emacswiki]]. =imaxima= is an =Emacs= front end with
image that displays fully typeset math in your =Emacs= window.
You must activate Maxima by adding a line to
=org-babel-load-languages=:
#+BEGIN_SRC emacs-lisp
(org-babel-do-load-languages
'org-babel-load-languages
'((maxima . t))) ; this line activates maxima
#+END_SRC
* Org Mode Features for Maxima Source Code Blocks
** Header Arguments
There are no Maxima-specific /default/ header arguments.
There are two Maxima-specific header arguments:
- =:batch= :: This can be set to one of Maxima's source-code loaders:
=batch=, =load= or =batchload=. The default loader is =batchload=.
- =:graphics-pkg= :: This can set to one of Maxima's graphics
packages: =draw= or =plot=. The default package is =plot=.
If a =:file filename.ext= header argument is provided to a Maxima
source block, in conjunction with a =:results graphics file= header
argument, then the graphics device is determined from the file-ending
=ext=. For the =plot= package, the following graphics devices (gnuplot
terminals) are supported:
#+begin_example
png, pdf, ps, svg.
#+end_example
The =draw= package supports these graphics devices:
#+begin_example
png, jpg, gif, eps, svg, pdf.
#+end_example
The header argument, =:cmdline=, can be used to pass command line
arguments to Maxima.
** Sessions
Org-mode support for Maxima does not include sessions.
** Result Types
Maxima produces the full range of result types.
* Examples of Use
** Calculator
The following source code block uses =maxima= as a calculator for
powers of 12, where the powers are passed with a variable.
#+begin_example
,#+name: test-maxima
,#+header: :exports results
,#+header: :var x=1.3121254
,#+begin_src maxima
programmode: false;
print(12^x);
,#+end_src
#+end_example
#+name: test-maxima
#+header: :exports results
#+header: :var x=1.3121254
#+begin_src maxima
programmode: false;
print(12^x);
#+end_src
HTML export of the result:
#+RESULTS: test-maxima
: 26.06280316745402
** Solver
Of course, =maxima= is more than a calculator.
#+begin_example
,#+name: solve-maxima
,#+header: :exports results
,#+begin_src maxima :results output
programmode: false;
eq: x**2-16 = 0;
solution: solve(eq, x);
print(solution);
,#+end_src
#+end_example
#+name: solve-maxima
#+header: :exports results
#+begin_src maxima :results output
programmode: false;
eq: x**2-16 = 0;
solution: solve(eq, x);
print(solution);
#+end_src
HTML export of the result:
#+RESULTS: solve-maxima
: solve: solution:
: x = - 4
: x = 4
: [%t1, %t2]
** 3D plots
With =gnuplot= installed (4.0 or higher), 3D graphics are possible.
This example is from [[http://maxima.sourceforge.net/maxima-gnuplot.html][a tutorial on the maxima/gnuplot interface]].
#+begin_example
,#+name: 3d-maxima
,#+header: :file images/maxima-3d.png
,#+header: :exports results
,#+header: :results file graphics
,#+begin_src maxima
programmode: false;
plot3d(atan(-x^2+y^3/4),[x,-4,4],[y,-4,4],[grid,50,50],[gnuplot_pm3d,true]);
,#+end_src
#+end_example
#+name: 3d-maxima
#+header: :file images/maxima-3d.png
#+header: :exports results
#+header: :results file graphics
#+begin_src maxima
programmode: false;
plot3d(atan(-x^2+y^3/4),[x,-4,4],[y,-4,4],[grid,50,50],[gnuplot_pm3d,true]);
#+end_src
HTML export of the Maxima code block result:
#+RESULTS: 3d-maxima
[[file:images/maxima-3d.png]]
** Inline Display of Maxima LaTeX Output
[[http://maxima.sourceforge.net/][Maxima]] code can be evaluated and displayed inline in Org mode
through babel [fn:1] as in the example below, based on RS initial
example.
#+begin_example
,#+NAME: tex-maxima
,#+HEADER: :exports results
,#+BEGIN_SRC maxima :results raw
tex(exp(-x)/x);
,#+END_SRC
#+end_example
#+NAME: tex-maxima
#+HEADER: :exports results
#+BEGIN_SRC maxima :results raw
tex(exp(-x)/x);
#+END_SRC
HTML export of the result:
#+RESULTS: tex-maxima
$${{e^ {- x }}\over{x}}$$
** The =:batch= header argument
Setting the =:batch= header argument to =batch=:
- allows the use of the =:lisp= reader;
- provides a more verbose output;
- allows one to typeset calculations in LaTeX.
*** An example with the =:lisp= reader
Sample code block:
#+name: batch-maxima.org
#+begin_src org :exports code :results replace
,#+NAME: batch-maxima
,#+HEADER: :batch batch
,#+HEADER: :exports results
,#+HEADER: :results raw
,#+HEADER: :wrap example
,#+BEGIN_SRC maxima
(assume(z>0), integrate(t^z*exp(-t),t,0,inf));
:lisp $%
,#+END_SRC
#+end_src
#+RESULTS: batch-maxima.org
#+NAME: batch-maxima
#+HEADER: :batch batch
#+HEADER: :exports results
#+HEADER: :results raw
#+HEADER: :wrap example
#+BEGIN_SRC maxima
(assume(z>0), integrate(t^z*exp(-t),t,0,inf));
:lisp $%
#+END_SRC
The first line of input computes the integral \(\int_0^{\infty}
t^z\,e^{-t}\,dt\), assuming that \(z\) is positive. The second input
line uses the =:lisp= reader to print the internal representation of
that result as a sexp.
HTML export of results:
#+RESULTS: batch-maxima
#+begin_example
(assume(z > 0),integrate(t^z*exp(-t),t,0,inf))
gamma(z + 1)
((%GAMMA SIMP) ((MPLUS SIMP) 1 $Z))
#+end_example
*** An example with line numbering
By default, the command-line option =--very-quiet= is passed to the
Maxima executable; this option suppresses the output of the start-up
banner and input/output labels. That can be modified by setting
=:cmdline --quiet=, which allows printing of input/output labels.
Sample code block:
#+name: batch-quiet-maxima.org
#+begin_src org :exports code :results replace
,#+NAME: batch-quiet-maxima
,#+HEADER: :batch batch
,#+HEADER: :exports results
,#+HEADER: :results raw
,#+HEADER: :wrap example
,#+HEADER: :cmdline --quiet
,#+BEGIN_SRC maxima
rat(1/(x+1) + x/(x-1));
,#+END_SRC
#+end_src
#+RESULTS: batch-quiet-maxima.org
#+NAME: batch-quiet-maxima
#+HEADER: :batch batch
#+HEADER: :exports results
#+HEADER: :results raw
#+HEADER: :wrap example
#+HEADER: :cmdline --quiet
#+BEGIN_SRC maxima
rat(1/(x+1) + x/(x-1));
#+END_SRC
HTML export of results:
#+RESULTS: batch-quiet-maxima
#+begin_example
(%i1) rat(1/(x+1)+x/(x-1))
2
x + 2 x - 1
(%o1)/R/ ------------
2
x - 1
#+end_example
Maxima's default is to print input in linear (or 1d) fashion, while
output is printed in 2d.
*** LaTeX output
To produce LaTeX output for an extended computation, one needs to
set-up a LaTeX printer. This example uses the ~alt-display~ package
to do that. To print output as LaTeX, Maxima's 2d printer is replaced
with ~org_tex_display~; to ensure input lines are not echoed, its 1d
printer is replaced with a sink, ~org_no_display~ (see also this
[[batch-note][Note]]).
Tangle this code block (=C-u C-c C-v t=):
#+comment: Ensure the block is evaluated (C-c C-c) after a change.
#+comment: Move to the results block and tangle it (C-u C-c C-v t)
#+name: maxima-initialize.lisp.org
#+begin_src org
,#+NAME: maxima-initialize.lisp
,#+HEADER: :tangle ./maxima-initialize.lisp
,#+HEADER: :exports none
,#+HEADER: :eval none
,#+begin_src maxima
#$(load("alt-display.mac"),
define_alt_display(org_no_display(output_form), ""),
define_alt_display(org_tex_display(output_form),
block([],
printf(true,"~+begin_example~%(~a~d)~%",outchar,linenum),
printf(true,"~+end_example~%"),
tex(second(output_form)))),
set_alt_display(2,org_tex_display),
set_alt_display(1,org_no_display));#$
,#+end_src
#+end_src
#+RESULTS: maxima-initialize.lisp.org
#+NAME: maxima-initialize.lisp
#+HEADER: :tangle ./maxima-initialize.lisp
#+HEADER: :exports none
#+HEADER: :eval none
#+begin_src maxima
#$(load("alt-display.mac"),
define_alt_display(org_no_display(output_form), ""),
define_alt_display(org_tex_display(output_form),
block([],
printf(true,"~+begin_example~%(~a~d)~%",outchar,linenum),
printf(true,"~+end_example~%"),
tex(second(output_form)))),
set_alt_display(2,org_tex_display),
set_alt_display(1,org_no_display));#$
#+end_src
Next, write a Maxima code block that sets the =:cmdline= header to
read in the initialization code that was just tangled.
#+name: batch-latex-maxima.org
#+begin_src org
,#+NAME: batch-latex-maxima
,#+HEADER: :batch batch
,#+HEADER: :exports results
,#+HEADER: :results raw
,#+HEADER: :wrap maximablock
,#+HEADER: :cmdline --quiet --preload-lisp ./maxima-initialize.lisp
,#+BEGIN_SRC maxima
(assume(z>0), 'integrate(t^z*exp(-t),t,0,inf) = integrate(t^z*exp(-t),t,0,inf));
diff(%,z);
,#+END_SRC
#+end_src
#+RESULTS: batch-latex-maxima.org
#+NAME: batch-latex-maxima
#+HEADER: :batch batch
#+HEADER: :exports results
#+HEADER: :results raw
#+HEADER: :wrap maximablock
#+HEADER: :cmdline --quiet --preload-lisp ./maxima-initialize.lisp
#+BEGIN_SRC maxima
(assume(z>0), 'integrate(t^z*exp(-t),t,0,inf) = integrate(t^z*exp(-t),t,0,inf));
diff(%,z);
#+END_SRC
HTML export of the results:
#+RESULTS: batch-latex-maxima
#+begin_maximablock
#+begin_example
(%o1)
#+end_example
$$\int_{0}^{\infty }{t^{z}\,e^ {- t }\;dt}=\Gamma\left(z+1\right)$$
#+begin_example
(%o2)
#+end_example
$$\int_{0}^{\infty }{t^{z}\,e^ {- t }\,\log t\;dt}=\psi_{0}(z+1)\,
\Gamma\left(z+1\right)$$
#+end_maximablock
*** <> Note
Prior to version =5.47=, Maxima could only pre-load a lisp
file; to get around this constraint, the Maxima code is written into a
lisp file, and the =#$= reader macro is used to read the Maxima code.
In versions 5.47 and higher, the Maxima code can be put in a =.mac=
file and pre-loaded without the need for such tricks.
** The =:graphics-pkg= header argument
The =:graphics-pkg= header argument can be set to use either Maxima's
built-in =plot= package (the default), or the =draw= package.
*** The =plot= package
The =plot= package is the default package that provides a simplified
interface to =gnuplot=. Here is an example that creates a =gif= file.
#+name: graphics-pkg--plot.org
#+begin_src org
,#+NAME: graphics-pkg--plot
,#+HEADER: :graphics-pkg plot
,#+HEADER: :file images/ob-maxima-plot.gif
,#+HEADER: :results graphics file
,#+HEADER: :exports both
,#+begin_src maxima
plot2d( sin(x), [x,0,2*%pi]);
,#+end_src
#+end_src
#+RESULTS: graphics-pkg--plot.org
#+NAME: graphics-pkg--plot
#+HEADER: :graphics-pkg plot
#+HEADER: :file images/ob-maxima-plot.gif
#+HEADER: :results graphics file
#+HEADER: :exports both
#+begin_src maxima
plot2d( sin(x), [x,0,2*%pi]);
#+end_src
HTML export of the results:
#+CAPTION: The graph of /sin(x)/ created with =plot=.
#+RESULTS: graphics-pkg--plot
[[file:images/ob-maxima-plot.gif]]
*** The =draw= package
The =draw= package has more features than =plot=, including an
object-oriented interface to several graphics engines, including
=gnuplot=. Here is an example that creates an =svg= file containing
the graph of a discontinuous function.
#+name: graphics-pkg--draw.org
#+begin_src org
,#+NAME: graphics-pkg--draw
,#+HEADER: :graphics-pkg draw
,#+HEADER: :file images/ob-maxima-draw.svg
,#+HEADER: :results graphics file
,#+HEADER: :exports both
,#+begin_src maxima
f(x) := if x>0 then cos(x) else if x<0 then 0;
draw2d(
line_width=2, grid=true, yrange=[-1.2,1.2],
explicit(f,x,0,%pi), explicit(f,x,-1,0),
fill_color=white, ellipse(0,0,0.05,0.05,0,360),
fill_color=blue , ellipse(0,1,0.05,0.05,0,360));
,#+end_src
#+end_src
#+RESULTS: graphics-pkg--draw.org
#+NAME: graphics-pkg--draw
#+HEADER: :graphics-pkg draw
#+HEADER: :file images/ob-maxima-draw.svg
#+HEADER: :results graphics file
#+HEADER: :exports both
#+begin_src maxima
f(x) := if x>0 then cos(x) else if x<0 then 0;
draw2d(
line_width=2, grid=true, yrange=[-1.2,1.2],
explicit(f,x,0,%pi), explicit(f,x,-1,0),
fill_color=white, ellipse(0,0,0.05,0.05,0,360),
fill_color=blue , ellipse(0,1,0.05,0.05,0,360));
#+end_src
HTML export of the results:
#+CAPTION: A discontinuous function plotted with =draw=.
#+RESULTS: graphics-pkg--draw
[[file:images/ob-maxima-draw.svg]]
**** Note
Internally, =ob-maxima= uses the function =set_draw_defaults=.
Because this function _overwrites_ the existing defaults, using it in
code blocks with the =:graphics-pkg draw= header argument will cause
the source block evaluation to fail silently.
* Additional Notes
** Toggle inline display of latex code
Latex code in org mode can be displayed inline by 'C-c C-x
C-l'. To remove the inline display 'C-c C-c' is used. This is
described further in the manual [fn:2].
** Set scale of output
If the inline display of the equations are illegible, the scale
can be set by customising the variable 'org-format-latex-options',
by setting the :scale variable to a value >1.
** Export
This exports nicely to both html (C-c C-e h h) and pdf (C-c C-e l
p). See [fn:3] and [fn:4] in the manual.
** Noweb expansion
_NOTE:_ I have not tested this yet, but as Eric Schulte noted on
the mailing list: "Alternately, if you really want to get fancy
you could use noweb expansion [fn:5] to insert the results of the
imaxima code block into a latex code block, and then use the
existing latex code block functionality to convert the imaxima
output to images of different types depending on the export
target." [fn:6]
** Footnotes
[fn:1] (info "(org)Library of Babel")
[fn:2] (info "(org)Previewing LaTeX fragments")
[fn:3] (info "(org)Exporting code blocks")
[fn:4] (info "(org)The export dispatcher")
[fn:5] (info "(org)noweb")
[fn:6] [[https://lists.gnu.org/archive/html/emacs-orgmode/2013-11/msg00893.html][Re: imaxima babel]]