How do I configure mathjax for iPython notebooks? - python

I'm trying to find a way for mathjax to not use STIX fonts for math in my iPython notebook. Instead, I'd much rather have it use the 'TeX' fonts. According to the documentation for Mathjax I should use:
MathJax.Hub.Config({
"HTML-CSS": {
preferredFont: "TeX"
}
});
That being said, I'm not sure where to put this. I've already tried putting this chunk of code into my custom.js file pertaining to my own ipython profile, but it doesn't work. Ideally, I'd like to make ipython profile specific adjustments for mathjax.

I recently had the exact problem. I really don't like the default STIX-Web font to render equation. After experimenting for a little while, I found a way to change the MathJax font in Jupyter Notebook. My Jupyter Notebook version is 4.3.1 and it is shipped with Anaconda. I assume the solutions for other versions should be similar.
I tried to edit custom.js both in /notebook/static/custom/custom.js and ~/.jupyter/custom/custom.js. Doesn't work. I also tried to edit mathjaxutils.js. It does nothing. Finaly I saw this post https://github.com/jupyter/help/issues/109. I realize Jupyter uses main.min.js to read MathJax configuration. So here is the solutions:
Download MathJax(https://github.com/mathjax/MathJax) from Github.
Unzip the MathJax file and go into the folder
copy jax/output/HTML-CSS/fonts/TeX into directoy ../notebook/static/components/MathJax/jax/output/HTML-CSS/fonts/
copy fonts/HTML-CSS/TeX into ../notebook/static/components/MathJax/fonts/HTML-CSS/
open ../notebook/static/notebook/js/main.min.js, search for availableFonts. It should be around line 14894. Change it to
...
availableFonts: ["STIX-Web","TeX"],
imageFont: null;
preferredFont: "TeX",
webFont: "TeX"
...
Refresh the notebook.

Jupyter ships with its own (smaller) version of MathJax. This is why it is not able to find the (Computer Modern) 'TeX' font -- there only is the STIX font.
To fix this, I was able to do the following:
Download MathJax 2.7 and copy the jax directory.
Replace Jupyter's jax directory with the copied one:
For the default environment: ~/anaconda3/lib/python3.7/site-packages/notebook/static/components/MathJax/jax
For a different environment: ~/anaconda3/envs/<ENVIRONMENT>/lib/python3.7/site-packages/notebook/static/components/MathJax/jax
Restart Jupyter, right-click on a piece of math and switch the 'Math Renderer' to SVG.
(Adjust python version in path if yours is not 3.7; If you are using miniconda the path should be ~/opt/miniconda3/lib/...)

A simple test to make sure that you're getting the configuration correct is to change preferredFont: "TeX" to scale: 200. Then save and reload a notebook. The math should be obviously way bigger than before. So assuming that worked, it means your config.js is doing what it needs to.
Now, more to the point, try adding another line so that your configuration looks like
MathJax.Hub.Config({
"HTML-CSS": {
availableFonts: ["TeX"],
preferredFont: "TeX",
}
});
Don't forget to fully refresh the notebook page after you've saved that. This overrides (what I'm guessing is) the default value of that availableFonts variable, which would allow STIX if mathjax can't find TeX. I'm not sure why it seems to ignore the preferred font, but this seems more like a mathjax issue than an ipython issue.
So now, if it still isn't in TeX font (which mathjax seems to call MathJax_Math-Italic.otf, or similar), I would guess that mathjax just can't find that font, and may have fallen back on something else. If that is the case, there's something messed up about your mathjax installation.

Take a look at some of the numericalmooc lessons such as this one where the MathJax configuration is included through a css file which is imported at some point in the notebook.

I've tweaked #Stefan Shi's answer to something a little easier, at least if you have the command-line svn installed.
Put the following into a script file called install_tex_fonts (install_tex_fonts.bat in Windows-land):
svn export https://github.com/mathjax/MathJax/trunk/fonts/HTML-CSS/TeX/woff fonts/HTML-CSS/TeX/woff
svn export https://github.com/mathjax/MathJax/trunk/jax/output/HTML-CSS/fonts/TeX jax/output/HTML-CSS/fonts/TeX
Move the script file into {PYTHON}/Lib/site-packages/notebook/static/components/MathJax where {PYTHON} is the root directory where you installed Python
Open a shell (command prompt) in this directory
Run the script by typing install_tex_fonts (or ./install_tex_fonts on *nix systems; I guess you also have to chmod a+x it)
Add the following section in your ~/.jupyter/custom/custom.js file (the $([IPython.events]).on('app_initialized.NotebookApp') line should already be there):
$([IPython.events]).on('app_initialized.NotebookApp', function(){
MathJax.Hub.Config({
"HTML-CSS": {
availableFonts: ["TeX"],
preferredFont: "TeX",
webFont: "TeX"
}
});

Following #Ian's information, you can get your initial HTML-CSS MathJax configuration from python with the below code (demjson is a soft requirement which allows us to partially process json in a javascript file: pip install demjson):
import sys
from pathlib import Path
MathJax_cfg_pth = (
Path(sys.executable).parents[0] /
# below path may differ
'Lib/site-packages/notebook/static/components/MathJax/jax/output/HTML-CSS/config.js'
)
with open(MathJax_cfg_pth, 'r') as f:
MathJax_cfg = f.read()
import demjson
start_cfg = MathJax_cfg.find("config:{") + 7
open_braces = 0
for i, c in enumerate(MathJax_cfg[start_cfg:]):
if c == '{':
open_braces += 1
elif c == '}':
if open_braces == 0:
break
open_braces -= 1
initial_configuration = demjson.decode(
MathJax_cfg[
start_cfg : start_cfg + i
].replace("(", "'(").replace(")", ")'")
)
Having this will be helpful if you want to revert any changes without restarting your notebook kernel. For the curious, my initial_configuration is here: https://pastebin.com/JkatcrAC
Next we can update a HTML-CSS MathJax setting in our current runtime by displaying HTML containing a short script. If you wanted to update the size of HTML-CSS displays you could use the following function:
from IPython.core.display import HTML
MathJax_scale_script = """
<script>
MathJax.Hub.Config({
"HTML-CSS": {
scale: %s
}
});
</script>
"""
def update_Math_size(size):
# 100 is default
display(HTML(MathJax_scale_script%size))
For example, update_Math_size(200) for double the size, and update_Math_size(100) to revert back to my default setting.

Related

How to move line (not cell) up/down in jupyter notebook using keyboard shortcut?

How can I move a line (or set of selected lines) down or up in jupyter notebook. Are there any shortcuts?
After moving line 3 one line up:
For example ALT+UP or ALT+DOWN is for up/down displacement that is used in Eclipse IDE.
This question discusses cell displacement.
TLDR:
By following this tutorial, I was able to enable all the sublime-text shortcuts (which includes the moving lines with Ctrl+Up/Ctrl/Down).
I then was able to furthermore, customize the shortcuts by editing the sublime.js
Complete answer:
Find your jupyter path with jupyter --config-dir
Add the following code to <JUPYTER-PATH>/custom/custom.js:
require(["codemirror/keymap/sublime", "notebook/js/cell", "base/js/namespace"],
function(sublime_keymap, cell, IPython) {
// setTimeout(function(){ // uncomment line to fake race-condition
cell.Cell.options_default.cm_config.keyMap = 'sublime';
var cells = IPython.notebook.get_cells();
for(var cl=0; cl< cells.length ; cl++){
cells[cl].code_mirror.setOption('keyMap', 'sublime');
}
// }, 1000)// uncomment line to fake race condition
}
);
You need to find this codemirror/keymap/sublime.js (that is required in the code from point 2), for me, it was in <MY-PYTHON-ENVIRONMENT>/lib/python3.8/site-packages/notebook/static/components/codemirror/keymap/sublime.js
At the end of this file, you can edit the shortcuts, in the keyMap.pcSublime section of this file (if you have a PC).
For OP, the lines to edit would be: swapLineUp and swapLineDown
I did this with Ubuntu & sublime installed.
You can select the line with mouse in jupyter notebook. Drag it
up or down before the line where you want to move it. Press >
button on keyboard while your text is still selected.
This will bring the cursor to end of selected line,
but before the text of line being replaced. Press Enter.
Since jupyter works with code blocks you can use that shortcut between code blocks as
Ctrl + Shift + -
But this will only works between code cells not in the same code block. I don't think there is a built-in shortcut for that. For more shortcuts you can look here: https://www.dataquest.io/blog/jupyter-notebook-tips-tricks-shortcuts/
There's no such a shortcut in Jupyter, however, you can manage your own shorcuts Go to Help > Edit keyboard Shortcuts and start setting your commands.
There's some good info on this other post which will lead you to manage your profile's notebook.json file and so on.
Hope this was useful ;)
Edit: typo
You can create your custom shortcuts in Jupyter notebook
Jupyter Shortcuts

pylint no member issue but code still works vscode

I have a very simple code here
import torch
l = torch.nn.Linear(2,5)
v = torch.FloatTensor([1, 2])
print(l(v))
under torch.FloatTensor, pylint in visual studio code claims that 'Module torch has no 'FloatTensor' member pylint(no-member).
However, the code works fine. Is this a false positive? How can I disable pylint for this specific instance?
Press: CTRL + Shift + P
Click on "Preferences: Open Settings (JSON)"
Add this line into JSON :
"python.linting.pylintArgs": ["--generated-members", "from_json,query"]
What worked for me was noticing what modules were giving those errors, which is torch for you, and then followed these steps:
hit CTRL + Shift + P
click on "Preferences: Open Settings (JSON)"
add the following to the JSON file you are presented with:
"python.linting.pylintArgs": [
"--generated-members", "torch.*"
]
for the sake of this answer, say that there were other modules giving problems, then you'd write:
"python.linting.pylintArgs": [
"--generated-members", "torch.* other_module.* next_module.*"
]
Yes it is a problem of Pylint
If you use Anaconda, you can do:
1. search python.linting.pylintPath in your VSCode setting
2. change it to (You Anaconda Path)\pkgs\pylint-1.8.4-py36_0\Scripts\pylint
You Anaconda Path and pylint-1.8.4-py36_0 may vary
A better answer to this question here: Why does it say that module pygame has no init member?
The answer above marked as the answer with references to Anaconda doesn't make sense to me, probably a newbie issue.
Please follow the link to get the real scoop, but to summarize -
Replacing extensionname with your problem module name, such as pygame or RPi or Torch:
Hit CTRL + Shift + P
Click on "Preferences: Open Settings (JSON)"
Add the following to the JSON file you are presented with (inside the {}, if there are entries already there add leading comma as well):
"python.linting.pylintArgs": [
"--extension-pkg-whitelist=extensionname" // comma separated
]
As Tomari says, it does work on windows.There is a little difference on linux. The path maybe like "(You Anaconda Path)/pkgs/pylint-2.6.0-py38_0/bin/pylint".

Jupyter Notebook: custom.js is not read

I am using Jupyter Notebook 5.6.0, in Python 2.7, on Windows 7. I have created %HOMEPATH%.jupyter\custom\custom.js file and added the following code to turn off autosave.
define([
'base/js/events'
],
function(IPython, events) {
events.on("notebook_loaded.Notebook",
function () {
IPython.notebook.set_autosave_interval(0); // Disable autosave
}
// Additional events.on() statements here
);
}
);
Unfortunately, it has no effect on autosave. However, the problem is not with the code (which one can find in various places), but the fact that Notebook does seem to even read custom.js, neither when the Notebook server starts nor when I open a ipynb file. Further actions I did:
1) I verified that it can find and read it using the appropriate Python code.
2) I added an alert() message in custom.js which is never shown
3) I added the following as an alternative for turning autosave off: Jupyter.notebook.set_autosave_interval(0); that I saw in some other post in stackoverflow.com.
Of course, none of these will have any effect if Notebook never reads custom.js. Any idea why is that happening?
... One day later:
I cleaned custom.js leaving only Jupyter.notebook.set_autosave_interval(0); Autosave is finally turned off! (So, most probably Notebook didn't like something in custom.js and rejected it totally!)
So I consider this question solved.

Find desktop folder in a custom location? [duplicate]

I have this small program and it needs to create a small .txt file in their 'My Documents' Folder. Here's the code I have for that:
textfile=open('C:\Users\MYNAME\Documents','w')
lines=['stuff goes here']
textfile.writelines(lines)
textfile.close()
The problem is that if other people use it, how do I change the MYNAME to their account name?
Use os.path.expanduser(path), see http://docs.python.org/library/os.path.html
e.g. expanduser('~/filename')
This works on both Unix and Windows, according to the docs.
Edit: forward slash due to Sven's comment.
This works without any extra libs:
import ctypes.wintypes
CSIDL_PERSONAL = 5 # My Documents
SHGFP_TYPE_CURRENT = 0 # Get current, not default value
buf= ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, buf)
print(buf.value)
Also works if documents location and/or default save location is changed by user.
On Windows, you can use something similar what is shown in the accepted answer to the question: Python, get windows special folders for currently logged-in user.
For the My Documents folder path, useshellcon.CSIDL_PERSONALin the shell.SHGetFolderPath() function call instead of shellcon.CSIDL_MYPICTURES.
So, assuming you have the PyWin32 extensions1 installed, this might work (see caveat in Update section below):
>>> from win32com.shell import shell, shellcon
>>> shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0)
u'<path\\to\\folder>'
Update: I just read something that said that CSIDL_PERSONAL won't return the correct folder if the user has changed the default save folder in the Win7 Documents library. This is referring to what you can do in library's Properties dialog:
The checkmark means that the path is set as the default save location.
I currently am unware of a way to call the SHLoadLibraryFromKnownFolder() function through PyWin32 (there currently isn't a shell.SHLoadLibraryFromKnownFolder. However it should be possible to do so using the ctypes module.
1Installers for the latest versions of the Python for Windows Extensions are currently available from: http://sourceforge.net/projects/pywin32

How to display line numbers in IPython Notebook code cell by default

I would like my default display for IPython notebook code cells to include line numbers.
I learned from Showing line numbers in IPython/Jupyter Notebooks that I can toggle this with ctrl-M L, which is great, but manual. In order to include line numbers by default, I would need to add something to my ipython_notebook_config.py file. Unless I've missed something, there is not an explanation of how to do this in the documentation.
(For Jupyter 4+) In the latest Jupyter versions, they have documented the place to make config changes. So basically, in the Jupyter update, they've removed the concept of profiles, so the custom.js file location is now .jupyter/custom/custom.js, depending on where your .jupyter folder is. So if you don't have a custom folder or the custom.js file, just create them, then put these lines into the newly created file:
define([
'base/js/namespace',
'base/js/events'
],
function(IPython, events) {
events.on("app_initialized.NotebookApp",
function () {
require("notebook/js/cell").Cell.options_default.cm_config.lineNumbers = true;
}
);
}
);
The above is for setting line numbers to all your cell types at the same time. Code, Markdown and Raw cells will all get line numbers if you do this. If you want line numbers only for code cells, there is a simpler approach. Select a code cell, open the Chrome/Firefox JavaScript console, type the following lines:
var cell = Jupyter.notebook.get_selected_cell();
var config = cell.config;
var patch = {
CodeCell:{
cm_config:{lineNumbers:true}
}
}
config.update(patch)
Then reload the page. These changes persist because Jupyter will create a json config file in .jupyter/nbconfig to store them. This method is from this page of the documentation, so read the docs for more config changes that you can make.
(old answer)
In the latest version of IPython Notebook (v3.1.0), go to ~/.ipython/<profile_name>/static/custom/custom.js and add these lines:
define([
'base/js/namespace',
'base/js/events'
],
function(IPython, events) {
events.on("app_initialized.NotebookApp",
function () {
IPython.Cell.options_default.cm_config.lineNumbers = true;
}
);
}
);
The IPython.Cell.options_default.cm_config.lineNumbers = true; line alone will not work as it needs to load the IPython.Cell object before it tries this. Adding this line alone will cause an undefined error in the console. You need to encase it in the event handler as shown.
#William-Denman's code might have worked for an earlier version, but now you will need to do this.
EDIT: The line of code right in the middle has to be changed to require("notebook/js/cell").Cell.options_default.cm_config.lineNumbers = true; for the latest version of IPython/Jupyter (IPython 4.0.0, Jupyter 4.0.6). The old IPython.Cell object will also work, but your web console will throw a deprecation warning, so you can expect the old line to not be supported in future versions.
Also, in the latest IPython/Jupyter, which I'm running using the WinPython portable, I couldn't find the custom.js file within the profile folder. I found it (after much searching) in WinPython-64bit-2.7.10.3\python-2.7.10.amd64\Lib\site-packages\notebook\static\custom. I don't know if this is a WinPython thing or a Jupyter thing. If someone has Jupyter (latest version) installed normally (using pip or whatever) and can still find the custom.js file in the profile folder, please comment.
In your custom.js file (location depends on your OS) put
IPython.Cell.options_default.cm_config.lineNumbers = true;
If you can't find custom.js, you can just search for it, but generally it will be in your profile_default folder. If it doesn't exist, create the file at $(ipython locate profile)/static/custom/custom.js
If for whatever reason that doesn't work, you can always edit the custom.js file in the site-packages/IPython/html/static/custom/ in the same way.
Above didn't work for me in 2018
I found that inside ~/.jupyter/nbconfig/notebook.json I needed to add to add the following lines:
"CodeCell": {
"cm_config": {
"lineNumbers": true
}
inside the object that was there. So the final object would look like:
{
"CodeCell": {
"cm_config": {
"lineNumbers": true
}
}
}

Categories