From 5f3fc8602c0eb1f6d0c072bd0c1a6bb883b8c9f9 Mon Sep 17 00:00:00 2001 From: Liu Hui Date: Wed, 5 Jul 2023 12:48:36 +0800 Subject: [PATCH] ob-python: Graphics output enhancement * lisp/ob-python.el (org-babel-python-graphics-output-function): New variable. (org-babel-execute:python): Allow to save graphics output with a user-defined function when the result type is `file graphics'. (org-babel-python-matplotlib-graphics-output): New helper function to generate code to save matplotlib-based graphics. --- lisp/ob-python.el | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lisp/ob-python.el b/lisp/ob-python.el index 0e0539d7a..4c304f83b 100644 --- a/lisp/ob-python.el +++ b/lisp/ob-python.el @@ -62,6 +62,14 @@ (defcustom org-babel-python-None-to 'hline :package-version '(Org . "8.0") :type 'symbol) +(defvar org-babel-python-graphics-output-function nil + "A function generating Python code for producing graphics output. +Specifically, for src blocks with `:results file graphics' header +argument, the code returned by the function will be appended to +the end of the src block and should produce the graphics file. +It can be set to `org-babel-python-matplotlib-graphics-output' +for matplotlib-based graphics.") + (defun org-babel-execute:python (body params) "Execute a block of Python code with Babel. This function is called by `org-babel-execute-src-block'." @@ -72,6 +80,9 @@ (defun org-babel-execute:python (body params) (cdr (assq :session params)))) (result-params (cdr (assq :result-params params))) (result-type (cdr (assq :result-type params))) + (graphics-file (and (member "graphics" result-params) + (ignore-errors + (org-babel-graphical-output-file params)))) (return-val (when (eq result-type 'value) (cdr (assq :return params)))) (preamble (cdr (assq :preamble params))) @@ -81,6 +92,10 @@ (defun org-babel-execute:python (body params) (org-babel-expand-body:generic body params (org-babel-variable-assignments:python params)) + (when graphics-file + (if (functionp org-babel-python-graphics-output-function) + (funcall org-babel-python-graphics-output-function + graphics-file params))) (when return-val (format (if session "\n%s" "\nreturn %s") return-val)))) (result (org-babel-python-evaluate @@ -149,6 +164,24 @@ (defun org-babel-python-table-or-string (results) res) res))) +(defun org-babel-python-matplotlib-graphics-output (out-file params) + "Return the Python code for saving graphics to `OUT-FILE'." + (let* ((allowed-args '(:dpi :format :backend)) + (args (mapconcat + (lambda (pair) + (if (member (car pair) allowed-args) + (format ",%s=%S" + (substring (symbol-name (car pair)) 1) + (cdr pair)) "")) + params ""))) + (format " +import matplotlib.pyplot +if len(matplotlib.pyplot.get_fignums()) > 0: + matplotlib.pyplot.gcf().savefig('%s'%s) +else: + raise RuntimeWarning('No figure is found')" + out-file args))) + (defvar org-babel-python-buffers '((:default . "*Python*"))) (defun org-babel-python-session-buffer (session) -- 2.25.1