Skip to content

Commit

Permalink
refactor to support :ipyfile plists
Browse files Browse the repository at this point in the history
Now you can set attributes for the outputs of images. We also use sha1 filenames now.
  • Loading branch information
jkitchin committed Feb 24, 2019
1 parent 8486b7f commit 80b70aa
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 43 deletions.
54 changes: 51 additions & 3 deletions scimax-ipython.org
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ f(1.41)
: 1.9880999999999998
:END:

A new feature for scimax users is the execution count, which shows you the counter for when the cell was executed. This shows as comment, so it won't appear in exported content. If you don't like the count, you can turn it off with this in your init files. It defaults to on.
A new feature for scimax users is the execution count, which shows you the counter for when the cell was executed. This shows as comment in the results, so it won't appear in exported content. The count is controlled by the output of the function defined in =ob-ipython-execution-count=. See the docstring of that variable for other options.

#+BEGIN_SRC emacs-lisp
(setq ob-ipython-suppress-execution-count nil)
(setq ob-ipython-execution-count 'ob-ipython-execution-count-suppress)
#+END_SRC


Ipython can have many kinds of output. The =# text/plain= line in the output tells you what kind of output this is. Later we will see how to filter these. If you don't like these lines, turn them off like this.

#+BEGIN_SRC emacs-lisp
Expand Down Expand Up @@ -89,6 +88,55 @@ x .dot. y = 1.3598389888491538
[[file:obipy-resources/19a94859c854121de1c305426d09b77e-647879Ej.png]]
:END:

** Add attributes to images in the output

You can use an =:ipyfile= header argument to put attributes on images in the output and to specify their filenames. This is helpful when writing technical documents so you can do things like make references to them like ref:clockwise and ref:counterclockwise, and when you want nice filenames for other purposes. We support :name, :filename, :caption, :attr_org, :attr_html and :attr_latex. These should be entered as a list of plists. It is necessary to quote the list.

#+BEGIN_SRC ipython :ipyfile '((:name "clockwise" :filename "obipy-resources/clockwise.png" :caption "A clockwise spiral.") (:name "counterclockwise" :filename "obipy-resources/counterclockwise.png" :caption "A counterclockwise spiral."))
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

t = np.linspace(0, 20 * np.pi, 350)
x = np.exp(-0.1 * t) * np.sin(t)
y = np.exp(-0.1 * t) * np.cos(t)

plt.plot(x, y)
plt.axis('equal')

plt.figure()
plt.plot(y, x)

plt.axis('equal')

print('Length of t = {}'.format(len(t)))
print('x .dot. y = {}'.format(x @ y))
#+END_SRC

#+RESULTS:
:results:
# output
Length of t = 350
x .dot. y = 1.3598389888491538



# image/png
#+caption: A clockwise spiral.
#+name: clockwise
[[file:obipy-resources/clockwise.png]]



# image/png
#+caption: A counterclockwise spiral.
#+name: counterclockwise
[[file:obipy-resources/counterclockwise.png]]
:end:




** Fine tune the output

By default we get all the outputs from the kernel. Here we get plain text, an image and a LaTeX representation.
Expand Down
133 changes: 93 additions & 40 deletions scimax-org-babel-ipython-upstream.el
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,11 @@ The overlays are not persistent, and are not saved."
;; I process the outputs one at a time here.
(s-join "\n\n" (loop for (type . value) in (append value display)
collect
(ob-ipython--render file (list (cons type value)))))))))
(ob-ipython--render
(if (memq type '(image/png image/svg))
(pop file)
file)
(list (cons type value)))))))))


;; ** Formatters for output
Expand Down Expand Up @@ -1098,53 +1102,102 @@ FILE-OR-NIL is not used in this function."
value)))


(defun ob-ipython--generate-file-name (suffix)
"Generate a file name to store an image in.
I added an md5-hash of the buffer name so you can tell what file
the names belong to. This is useful later to delete files that
are no longer used."
(s-concat (make-temp-name
(concat (f-join ob-ipython-resources-dir (if-let (bf (buffer-file-name))
(md5 (expand-file-name bf))
"scratch"))
"-"))
suffix))


(defun ob-ipython-format-image/png (file-or-nil value)
"Format VALUE for image/png mime-types.
FILE-OR-NIL if non-nil is the file to save the image in. If nil,
a filename is generated."
(let ((file (or file-or-nil (ob-ipython--generate-file-name ".png"))))
(ob-ipython--write-base64-string file value)
(s-join "\n" (list
(if ob-ipython-show-mime-types "# image/png" "")
(format "[[file:%s]]" file)))))


(defun ob-ipython--write-base64-string (file b64-string)
"Write to FILE the image in B64-STRING.
Note: the original version of this would sometimes hang, so I
rewrote this."
(if b64-string
(progn
(unless (file-directory-p (file-name-directory file))
(make-directory (file-name-directory file) t))
(with-temp-file file
(insert (base64-decode-string b64-string))))
(error "No output was produced to write to a file.")))
FILE-OR-NIL if non-nil is either a plist of values or a string."
(let ((require-final-newline nil)
(file (cond
;; A string is the filename
((stringp file-or-nil) file-or-nil)
;; You specified a filename
((and (listp file-or-nil) (plist-get file-or-nil :filename))
(plist-get file-or-nil :filename))
;; make a filename
(t
(f-join ob-ipython-resources-dir
(if-let (bf (buffer-file-name))
(sha1 (expand-file-name bf))
"scratch")
(concat (sha1 value) ".png"))))))
;; Write file to disk
(when (file-name-directory file)
(unless (file-directory-p (file-name-directory file))
(make-directory (file-name-directory file) t)))
(with-temp-file file
(insert (base64-decode-string value)))

;; Return the string for the result
(s-join
"\n"
(remove nil
(list
(if ob-ipython-show-mime-types "# image/png" "")
(when (listp file-or-nil)
(when-let (attr (plist-get file-or-nil :attr_org))
(format "#+attr_org: %s" attr)))
(when (listp file-or-nil)
(when-let (attr (plist-get file-or-nil :attr_html))
(format "#+attr_html: %s" attr)))
(when (listp file-or-nil)
(when-let (attr (plist-get file-or-nil :attr_latex))
(format "#+attr_latex: %s" attr)))
(when (listp file-or-nil)
(when-let (caption (plist-get file-or-nil :caption))
(format "#+caption: %s" caption)))
(when (listp file-or-nil)
(when-let (name (plist-get file-or-nil :name))
(format "#+name: %s" name)))
(format "[[file:%s]]" file))))))


(defun ob-ipython-format-image/svg+xml (file-or-nil value)
"Format VALUE for image/svg+xml mime-types.
FILE-OR-NIL if non-nil is the file to save the image in. If nil,
a filename is generated."
(let ((file (or file-or-nil (ob-ipython--generate-file-name ".svg"))))
(ob-ipython--write-string-to-file file value)
(s-join "\n"
(list
(if ob-ipython-show-mime-types "# image/svg" "")
(format "[[file:%s]]" file)))))
(let ((require-final-newline nil)
(file (cond
;; A string is the filename
((stringp file-or-nil) file-or-nil)
;; You specified a filename
((and (listp file-or-nil) (plist-get file-or-nil :filename))
(plist-get file-or-nil :filename))
;; make a filename
(t
(f-join ob-ipython-resources-dir
(if-let (bf (buffer-file-name))
(sha1 (expand-file-name bf))
"scratch")
(concat (sha1 value) ".svg"))))))
;; Write file to disk
(when (file-name-directory file)
(unless (file-directory-p (file-name-directory file))
(make-directory (file-name-directory file) t)))

(with-temp-file file
(insert value))

;; Return the string for the result
(s-join
"\n"
(remove nil
(list
(if ob-ipython-show-mime-types "# image/svg" "")
(when (listp file-or-nil)
(when-let (attr (plist-get file-or-nil :attr_org))
(format "#+attr_org: %s" attr)))
(when (listp file-or-nil)
(when-let (attr (plist-get file-or-nil :attr_html))
(format "#+attr_html: %s" attr)))
(when (listp file-or-nil)
(when-let (attr (plist-get file-or-nil :attr_latex))
(format "#+attr_latex: %s" attr)))
(when (listp file-or-nil)
(when-let (caption (plist-get file-or-nil :caption))
(format "#+caption: %s" caption)))
(when (listp file-or-nil)
(when-let (name (plist-get file-or-nil :name))
(format "#+name: %s" name)))
(format "[[file:%s]]" file))))))


(defun ob-ipython-format-application/javascript (file-or-nil value)
Expand Down

0 comments on commit 80b70aa

Please sign in to comment.