1

The context

Consider the following Emacs configuration

$ cat ~/.emacs.d/init.el
(org-babel-do-load-languages 'org-babel-load-languages
                             '((python . t)))
$

and the following Org mode file

$ cat ~/Experiments/main.org
#+begin_src python :tangle main.py :results file :file 1.png
from matplotlib import pyplot
x = [1, 2, 3]
y = [1, 4, 9]

pyplot.plot(x, y)
pyplot.savefig('1.png')
#+end_src
$

If I tangle the Python code block (i.e. execute org-babel-tangle), execute the Python script (i.e. execute python main.py in a shell) and obtain the hash of the resulting image I get

$ pwd
/home/myusername/Experiments
$ python main.py
$ sha512sum 1.png && du -h 1.png
084ffd63ec53665c21fc3eaba5f5ec3622d4d27a97f89cb67e3b436ca8093467272bbc239fd0e60dde27f5207ee33392f5b83b9eca1427efe7523450d92a6a8c  1.png
20K    1.png

I can open 1.png with firefox and mpv without any problems.

If I execute the code block in Emacs by pressing C-c C-c (i.e. execute org-babel-execute-src-block) while the cursor is in the #+BEGIN_SRC block, I get the following

$ sha512sum 1.png && du -h 1.png
e39d05b72f25767869d44391919434896bb055772d7969f74472032b03bc18418911f3b0e6dd47ff8f3b2323728225286c3cb36914d28dc7db40bdd786159c0a  1.png
4.0K    1.png

Note that the size of 1.png is significantly lower than the size shown above.

Additional context

In addition to that, if I try to open the image with mpv, I get the following error

$ mpv 1.png
 (+) Video --vid=1 (png 1.000fps)
[ffmpeg/video] png: Invalid PNG signature 0x00000000.
Error while decoding frame!
(Paused) V: 00:00:01 / 00:00:01 (100%)
[ffmpeg/video] png: Invalid PNG signature 0x00000000.
Error while decoding frame!
(Paused) V: 00:00:01 / 00:00:01 (100%)

An error is also shown when I try to open the image in firefox (see image below)

enter image description here

The error is not present in both firefox and mpv when producing the image 1.png by executing the script in a shell.

The question

  • Why is the file 1.png obtained after executing org-babel-execute-src-block different than the one produced by tangling the #+BEGIN_SRC block and executing python main.py in a shell?
  • Why does the resulting file 1.png contain errors?
3

Change :results file to :results file graphics.

1
  • Thanks. It solved the issue! I will have to read on the graphics header argument I think. – doltes Nov 3 '20 at 1:22
1

Here's an explanation to go with @darcamo's answer:

When you say :results file :file 1.png, babel creates a file 1.png containing the result of running the block (in the default case of :results value) or the standard output (in the :results output case) and puts a link to that file as the result of the evaluation of the block.

In your case, the source block returns the value that pyplot.savefig(...) returns, which happens to be None. The block also writes the image into 1.png (that's what savefig() does after all), but then babel saves the result and overwrites the image with the word None. So you end up with a "corrupt" PNG file: check it with ls -l and cat: it's 4 bytes long containing the characters None.


OTOH, when you say :results file link :file 1.png (or :results file graphics :file 1.png - they do the same thing), babel just puts a link to a (non-existent) file called 1.png as the result of the evaluation but does not create the file. It just runs the block which, as a side effect, produces the file 1.png - a real PNG file in this case, since babel does not overwrite it. Note that there is a conspiracy involved: babel creates a link to 1.png but has no idea what file (if any) the block is going to produce: you have to make sure that the file produced by the block has the same name - if the names are different, then the link is not going to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.