Open amueller opened 8 years ago
Do you want the reference to work in the live notebook itself, or a PDF export?
Ideally both. For me the PDF export (and markup export) are more important.
FYI, this is for a book I'm writing. Other authors have similar problems. What I didn't realize when posting the original issue is that ideally you'd be able to reference across multiple notebooks, which seems quite tricky. If it would possible to solve this for a single notebook, maybe there would be a way to say "this is chapter X" so that figures would be numerated Figure X.Y.
There are a bunch of people writing books, for example for O'Reilly, and running in similar issues. Maybe O'Reilly could help with this? You worked with them before, right?
One idea to do this is adding a new image writer (see IPython.display.set_matplotlib_formats and what it does...), which wraps the matplotlib image by sending markdown/HTML down the wire instead of the image itself. This markdown would embedded the image in a data URL (which currently does not diplay in the notebook: https://github.com/jupyter/notebook/issues/789) and get the caption from a global variable.
like `
set_caption("...")
plot(...)
...
Another idea is to add a special function which does the image display. So producing a plot becomes:
# without `%%maptlotlib inline`!
display_plot(fig, "Caption")
And this would then produce a html/markdown string with the image embedded in the data URL and this is then displayed.
If it is possible to add a context while doing the nbconvert, then you could --as a workaround for the markdown data URL problem form above-- send the caption as html and the image as normal image while in a normal notebook and while in the nbconvert process sent a markdown with the embedded data URL formatted like knitr does it. This then becomes a ipnb -> markdown -> latex -> pdf (the last steps via pandoc).
[Or maybe I misread the bugreport and it is possible to send data URLs with html/markdown content from the kernel, but not from the markdown cells]
So what I would suggest is writing a custom display-formatter that specialize figures.
Technically we can likely add the equivalent of a _repr_rst_
if rest is the thing you like to use. THen you can do whatever you like from your code. You could even inject this repr in startup.py, so no need to instanciate it in the notebook.
Nbconvert will need to be modifed to pick-up the rst format at conversion time, buts that's likely doable.
Beyond generating only the rest repr, you can also attach metadata to the object, to "fix" the rst at conversion time.
from IPython.core.formatters import BaseFormatter
from traitlets import Unicode
class RESTFormatter(BaseFormatter):
"""An ReST formatter.
"""
format_type = Unicode('text/rst')
#print_method = ObjectName('_repr_rest_') #optionnal if custom object later
rf = RESTFormatter()
ip = get_ipython()
ip.display_formatter.formatters['text/rst'] = rf
class Foo():pass
def f(*args, **kwargs):
return """
.. figure::
:your:
Figure here
""", {'meta':'data'}
rf.for_type(Foo, f)
(too be adapted)
will make the following:
In[1]: Foo()
to be the following in the ipynb:
"outputs": [
{
"data": {
...
"text/rst": [
"\n",
".. figure::\n",
" :your:\n",
"\n",
" Figure here\n"
]
},
...
"metadata": {
"text/rst": {
"meta": "data"
}
},
...
}
],
"source": [
"ff"
]
}
That would be your part to do I guess (or even publish a ipython-RST-formatter on PyPI)
Next step need custom templates/exporter for nbviewer, possibly using master; is using master a problem ?
I'm going to tag this as "Docs", it's technically not notebook, it's both kernelside (in your case IPython) coupled with nbconvert, but it's likely a good place to start for someone who wants to improve the docs, and a nice use case.
I'm already using nbconvert master (that's what you meant, right)? I needed to fix some bugs ;) I need to think through your solution, but that sounds doable.
Possibly stupid question: If this is done in the RST formater, then other output formats couldn't use the info, right? (clickable?) figure references make sense for latex, html and RST, at least.
So I'm probably gonna do this for latex first. @Carreau, I have to admit I don't understand what is going on in your example. How would I use the formatter? In a custom preprocessor? I tried understanding this solution: http://blog.juliusschulz.de/blog/ultimate-ipython-notebook but that requires manually adding metadata in the cell for each figure (and then changing the latex template).
Is there any documentation on this? I was hoping to find some here: http://ipython.readthedocs.org/en/stable/development/index.html but didn't...
Is there still no movement on figure captions in jupyter notebooks? Note that I disagree with @Carreau that this is a kernel issue. ReST is also not the only output one would want to support that — it is also useful for html. imho this post by Julius Schulz comes closest to what one would want: captions for arbitrary cells that any converter could come and deal with as it pleases. All we would need is:
The converters would follow. Are there any prospects for such support?
I want to refer to figures created by code cells in my markup. Is there a nice way to do this? I'm working in a book and I want to say "See figure X" like I would in latex, where figure X is created by some cell further up.
There seems to be some work for formulas which seems somewhat related: https://github.com/ipython/ipython/issues/4113
[this seems like a jupyter notebook question, so I post here, not there]