How can I setup a MathJax "preamble" for use in IPython (or Jupyter) notebooks for repeated use in a way that is convenient for others to read my documents (on http://nbviewer.org) and that works for LaTeX/PDF generation?
I would like to use IPython (now Jupyter) notebooks for documents that I later convert to PDF via LaTeX (using ipython nbconvert
). The problem is how to include a bunch of macro definitions that I use in almost every document. Something like:
\newcommand{\vect}[1]{\vec{#1}}
\newcommand{\abs}[1]{\lvert#1\rvert}
\DeclareMathOperator{\erf}{erf}
etc. As far as the notebooks is concerned, one unsatisfactory solution is to simply include these in a markdown cell at the top of the notebook, embeded between two dollar signs $$
so it is interpreted as math. If this is done after some introductory text, then it does not even affect the output.
The problem is that, when converting to LaTeX (for PDF export), these commands are embedded in a math environment in the LaTeX file. This has several problems:
\DeclareMathOperator
must come in the LaTeX document preamble.\gdef
or \global\def
but then one must trick MathJax into recognising these commands with something like \let\gdef{\def}
which is somehow hidden from LaTeX. Any way I have found of making this work amounts to an ugly hack.)\renewcommand
(not supported by MathJax, but again can be provided by \let\renewcommand\newcommand
etc. which seems reasonable to me since MathJax can't have some idea of what preamble might be used for the final LaTeX file).Probably the solution is to provide a set of macros to MathJax by adding code like (not sure the equivalent of \DeclareMathOperator
here...)
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
TeX: {
Macros: {
vect: ["{\\vec #1}",1],
abs: ["{\\lvert #1 \\rvert}",1]
}
}
});
</script>
to a custom.js
file and then providing a LaTeX package for inclusion when converting to PDF. The problem I have with this approach is: How to distribute the custom.js
file and LaTeX style file for others (collaborators and viewers) to use?
I want collaborators to be able to edit and read my documents without having to install custom extensions in their global configuration. To be specifiec, I am fine with requiring them to run a command like python setup.py configure
once they download/checkout my code which does local modifications to the project like populating ipython_notebook_config.py
files in all directories containing notebooks, but am not happy installing extensions, or modifying their personal global custom.js
file.
My stumbling block here is that I don't know how to add contributions from a local custom.js
file to the notebook chain, and suspect that this might violate a security policy.
The best solution would not require any action on my collaborator's part.
I want my notebooks to work on http://nbviewer.org, and for people to be able to download the notebook and produce a PDF. (I think this rules out the possibility of using custom.js
hacks and a distributed *.sty
file, but am not certain.)
I would prefer to be able to simply start a new notebook and then start writing without having to insert a bunch of boilerplate code at the start of each notebook, though would be amenable to having a simple way of automating this process using an notebook extension or some hooks in python_notebook_config.py
.
The following posts address some of these issues, but fall short on most fronts:
Discussions about (potential) problems with the pandoc production of LaTeX files from IPython notebooks:
General discussion of math in notebooks:
The Jupyter Notebook uses MathJax to render LaTeX inside HTML / Markdown. Just put your LaTeX math inside $ $ . Or enter in display math mode by writing between $$ $$ . The [n] is optional.
Jupyter Book uses MathJax for typesetting math in your HTML book build. This allows you to have LaTeX-style mathematics in your online content.
I think you can solve some of your problems, but not all.
First, the stumbling block. I believe (though I might be wrong) that nbviewer doesn't look at anything but the notebook itself. For example, I don't see how it could run an ipython_notebook_config.py
stored alongside your notebook. So that rules out that line of thought, meaning that I think you'll have to bite the bullet and add boilerplate to every notebook. But you might at least be able to minimize the boilerplate. In that vein:
You could maintain your custom.js
(probably under a more descriptive name) on github or whatever, and then add one line of boilerplate to all your notebooks to load that script from the URL. You would still need boilerplate, but it would be a lot shorter.
Once you have executed the code cell containing the javascript, it is saved in the notebook, which means that it will automatically happen the next time the browser loads it, even before the code cell is executed. So unless nbviewer prevents the javascript's execution, it should work just fine. This would also make things work nicely for collaborators, since they wouldn't have to download additional files.
As for your own style file, I suspect that anyone sophisticated enough to install ipython and latex, download your notebook, and run nbconvert
on it would also be sophisticated enough to download the .sty
file. Anyway, I don't see any way around the need to do that...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With