From: Leo Butler <Leo.Butler@umanitoba.ca>
To: Max Nikulin <manikulin@gmail.com>
Cc: "emacs-orgmode@gnu.org" <emacs-orgmode@gnu.org>
Subject: Re: [TIP] Exporting Maxima results to LaTeX
Date: Tue, 14 Feb 2023 15:13:52 +0000 [thread overview]
Message-ID: <87wn4ks2j5.fsf@t14.reltub.ca> (raw)
In-Reply-To: <28dbe348-ad7a-dfb2-3fcf-00d8555de967@gmail.com> (Max Nikulin's message of "Sat, 11 Feb 2023 18:39:56 +0700")
[-- Attachment #1: Type: text/plain, Size: 1020 bytes --]
On Sat, Feb 11 2023, Max Nikulin <manikulin@gmail.com> wrote:
> On 09/02/2023 03:40, Leo Butler wrote:
>> On Wed, Feb 08 2023, Max Nikulin wrote:
>>> I am curious if it is possible to avoid duplication by e.g. using noweb.
>>
>> ... I am not aware of how to
>> remove that duplication--all the examples I have found in the worg
>> source do what I have done above.
>
> I have tried
<snip>
Recursive evaluation of code blocks! Of course! THANK YOU!
>
> For debugging of the inner src block it is necessary to swap escaping
> with the outer #+begin_src.
Yes, it should be possible to recursive edit in indirect buffers. I
don't see how to do that.
> I have not figured out how to add some text in between of the exported
> source code example and its result.
See the attached. You need to name a code block and manually insert the
#+RESULT: stanza where you want the result put.
Thanks to Max and Eric for their comments. I have incorporated the
comments in the attached.
Leo
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: maxima-tip.org --]
[-- Type: text/x-org; name="maxima-tip.org", Size: 7145 bytes --]
#+TITLE: Tip for exporting Maxima results to LaTeX
#+AUTHOR: Leo Butler
#+OPTIONS: H:3 toc:t num:t tags:nil todo:nil
#+LATEX_CLASS: article
#+LATEX_HEADER: \usepackage{color} \usepackage[margin=2cm]{geometry}
#+LATEX_COMPILER: lualatex
#+PROPERTY: header-args:maxima :eval export :exports results :results raw drawer
* Goal
Generate LaTeX code from Maxima code.
* Setup
** maxima-init.lisp
The command =org-babel-execute:maxima= in =lisp/ob-maxima.el= uses the Maxima command ~batchload~ to execute Maxima code. This is a very tight-lipped loader, so we over-write ~batchload~ with ~batch~. We also ~load~ an init file:
#+name: maxima-init.lisp.org
#+begin_src org :exports code :results replace
,#+name: maxima-init.lisp
,#+begin_src maxima :tangle maxima-init.lisp :exports none
(defun $batchload (file) (mfuncall '$batch file))
($load "./maxima-init.mac")
,#+end_src
#+end_src
On tangling, this produces the ~common-lisp~ output file ~maxima-init.lisp~. It will be pre-loaded into Maxima.
#+RESULTS: maxima-init.lisp.org
#+name: maxima-init.lisp
#+begin_src maxima :tangle maxima-init.lisp :exports none
(defun $batchload (file) (mfuncall '$batch file))
($load "./maxima-init.mac")
#+end_src
** maxima-init.mac
Next, we need to create an init file for Maxima that will provide an output printer that produces @@latex:\LaTeX{}@@ output. One option would be to use the ~imaxima~ printer. Here is another option that uses the ~alt-display~ package.
The code replaces the default printer with ~org_tex_display~. It also sets the ~epilog~ prompt, so that the final ~#+begin_example~ is terminated.
#+name: maxima-init.mac.org
#+begin_src org :exports code :results replace
,#+name: maxima-init.mac
,#+begin_src maxima :tangle maxima-init.mac :exports none :eval none
load("alt-display.mac") $
set_prompt('epilog,printf(false,"~%#+end_example")) $
define_alt_display(org_tex_display(x),
block([],
printf(true,"#+end_example~%#+begin_export latex~%"),
printf(true,"\\textcolor{blue}{(\\~a~d)} ",outchar,linenum-1),
tex(second(x)),
printf(true,"~&#+end_export~%#+begin_example~%(input) "))) $
set_alt_display(2,org_tex_display) $
display2d:true $
printf(true,"#+begin_example~%(input) ") $
linenum : 0 $
,#+end_src
#+end_src
#+RESULTS: maxima-init.mac.org
#+name: maxima-init.mac
#+begin_src maxima :tangle maxima-init.mac :exports none :eval none
load("alt-display.mac") $
set_prompt('epilog,printf(false,"~%#+end_example")) $
define_alt_display(org_tex_display(x),
block([],
printf(true,"#+end_example~%#+begin_export latex~%"),
printf(true,"\\textcolor{blue}{(\\~a~d)} ",outchar,linenum-1),
tex(second(x)),
printf(true,"~&#+end_export~%#+begin_example~%(input) "))) $
set_alt_display(2,org_tex_display) $
display2d:true $
printf(true,"#+begin_example~%(input) ") $
linenum : 0 $
#+end_src
* An example
Here is an example that computes the partial derivatives of a composite function.
** Org code
#+name: chain-rule.org
#+begin_src org :exports both :results replace
,#+name: chain-rule
,#+begin_src maxima :exports both :cmdline -p ./maxima-init.lisp
(gradef(f(u,v),f_1(u,v),f_2(u,v)), 'done);
diff(f(x^2-y^2,x*y),x);
diff(f(x^2-y^2,x*y),y);
,#+end_src
#+end_src
** Maxima code
#+RESULTS: chain-rule.org
The first line defines the partial derivatives of \(f(u,v)\) with repect to \(u\) and \(v\). The second and third lines compute the partial derivatives of the composite \(f(x²-y²,xy)\).
** Result of evaluation; LaTeX output
The ~batch~ printer echos each input line; it prints the output of
each command line that ends in a semi-colon (=;=). The result of a
line ending in a dollar sign (=$=) is not printed. The
~org_tex_display~ printer wraps each echoed input line in an ~example~
block and prints the output as it would appear in an =imaxima=
session.
#+RESULTS: chain-rule
** Two annoyances
The initial line =read and interpret...= and that final, dangling
input line with ~gnuplot_close()~ are nuisances. They can be easily
suppressed, but that requires patching ~ob-maxima.el~. That's another
story.
* Epilogue
After sending my initial draft to the =Org= mailing list, I received some feedback.
** Eric Fraga's suggestion
:PROPERTIES:
:header-args:maxima:
:END:
On the mailing list, Eric Fraga suggested adding the prologue/epilogue:
#+begin_example
#+PROPERTY: header-args:maxima :prologue "fpprintprec: 2; linel: 50;"
#+PROPERTY: header-args:maxima :epilogue "for j: 1 thru length(solution) do (\
print(\"\"), print(\"Solution\", j), \
print(\"\"), for i: 1 thru length(solution[j]) do grind(solution[j][i]))$"
#+end_example
\normalsize
Let's redo the example above with those settings and incorporating Eric's design that the results need to be collected in the ~solution~ list:
#+name: fraga-example.org
#+begin_src org :exports both :results replace :noweb yes
,#+name: chain-rule-redo
,#+header: :prologue "fpprintprec: 2; linel: 50;"
,#+header: :epilogue "for j: 1 thru length(solution) do (print(\"\"), print(\"Solution\", j), print(\"\"), for i: 1 thru length(solution[j]) do grind(solution[j][i]));"
,#+begin_src maxima :exports results :results table
(gradef(f(u,v),f_1(u,v),f_2(u,v)), 'done);
fx:diff(f(x^2-y^2,x*y),x);
fy:diff(f(x^2-y^2,x*y),y);
solution:[fx,fy];
,#+end_src
#+end_src
#+RESULTS: fraga-example.org
Here is the result:
#+RESULTS: chain-rule-redo
** Max Nikulin's idea
Max Nikulin remarked that the ~org~ code in this file contains redundancy. He suggested trying:
#+name: elisp-in-org-in-org
#+begin_src org :exports both :results replace
,#+begin_src elisp :exports results :results silent
(require 'ob-org)
,#+end_src
,#+name: elisp-in-org
,#+begin_src org :exports both :results replace
,,#+name: elisp-block
,,#+begin_src elisp :exports results
'((1 2 3) (4 5 6))
,,#+end_src
,#+end_src
#+end_src
The block named ~elisp-in-org~ is exported to:
#+RESULTS: elisp-in-org-in-org
The ~elisp~ code block exports to a named block of =elisp= code.
#+RESULTS: elisp-in-org
That exports to:
#+RESULTS: elisp-block
*** A bug // Feature request
=Org= does a good job of recursively evaluating code blocks, as can be seen by the examples here (Thanks, Max!). But, two things are not done quite correctly:
1. When editing ~org~ code blocks in an indirect buffer, it should be possible to recursively edit a code block. That does not appear to work at the moment.
2. Noweb expansion does not work correctly in combination with recursive evaluation of code blocks. In the ~org~ block named =fraga-example.org=, a noweb reference =<<chain-rule>>= to the Maxima code block =chain-rule= is not expanded correctly (it leaves a blank line).
* How to reproduce the pdf
1. In this =org= file, do ~C-c C-v t~ to tangle the two code blocks.
2. Then, do ~C-c C-e l p~ to export to pdf. Each time you are prompted about evaluating a code block, answer ~y~ or ~yes~.
[-- Attachment #3: maxima-tip.pdf --]
[-- Type: application/pdf, Size: 53439 bytes --]
prev parent reply other threads:[~2023-02-14 15:19 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-07 21:40 [TIP] Exporting Maxima results to LaTeX Leo Butler
2023-02-07 22:13 ` Thomas S. Dye
2023-02-08 15:43 ` Max Nikulin
2023-02-08 16:11 ` Fraga, Eric
2023-02-08 20:40 ` Leo Butler
2023-02-11 11:39 ` Max Nikulin
2023-02-14 15:13 ` Leo Butler [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87wn4ks2j5.fsf@t14.reltub.ca \
--to=leo.butler@umanitoba.ca \
--cc=emacs-orgmode@gnu.org \
--cc=manikulin@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).