-
Notifications
You must be signed in to change notification settings - Fork 207
[MRG+1]: Allow unicode in code and outputs #106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1a6ac2e
a910e55
7952f21
2b53be7
7aa20a8
e7a7bd4
78793ca
4852d90
e8d9fed
33c1893
81bd239
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# -*- coding: utf-8 -*- | ||
r""" | ||
================================================= | ||
Some Quantum Mechanics, filling an atomic orbital | ||
================================================= | ||
|
||
Considering an atomic single orbital and how to fill it by use of the | ||
chemical potential. This system has a four element basis, :math:`B = | ||
\{ \lvert \emptyset \rangle, \lvert \uparrow \rangle, \lvert | ||
\downarrow \rangle, \lvert \uparrow\downarrow \rangle \}`, that is the | ||
empty orbital, one spin up electron, one spin down electron and the | ||
filled orbital. | ||
|
||
The environment of the orbital is set up by an energy cost for | ||
occupying the orbital, that is :math:`\epsilon` and when both | ||
electrons meet a contact interaction corresponding to the Coulomb | ||
repulsion :math:`U`. Finally the chemical potential :math:`\mu` is | ||
what allows in the Grand canonical picture, to fill up our atomic | ||
orbital from a reservoir of electrons. | ||
|
||
The the simple Hamiltonian to model this system is given by: | ||
|
||
.. math:: | ||
\mathcal{H} = | ||
\sum_{\sigma=\uparrow,\downarrow} \epsilon c^\dagger_\sigma c_\sigma | ||
+ Un_\uparrow n_\downarrow - \mu \hat{N} | ||
|
||
Here :math:`c^\dagger,c` creation and annihilation operators, | ||
:math:`n=c^\dagger c`, and | ||
:math:`\hat{N}=n_\uparrow+n_\downarrow`. This Hamiltonian is diagonal | ||
in the basis of particle number we have chosen earlier, as the basis | ||
elements are also eigenvectors. | ||
|
||
.. math:: | ||
\mathcal{H} \lvert \emptyset \rangle &= 0 \\ | ||
\mathcal{H} \lvert \uparrow \rangle &= (\epsilon - \mu) | \uparrow \rangle \\ | ||
\mathcal{H} \lvert \downarrow \rangle &= (\epsilon - \mu) | \downarrow \rangle \\ | ||
\mathcal{H} \lvert \uparrow\downarrow \rangle &= (2\epsilon - 2\mu +U) \lvert \uparrow\downarrow \rangle | ||
|
||
It is easy to see, that the system will prefer to be empty if | ||
:math:`\mu \in [0,\epsilon)`, be single occupied if :math:`\mu \in (\epsilon, \epsilon +U)` | ||
and doubly occupied if :math:`\mu > \epsilon +U`. | ||
|
||
For a more rigorous treatment, the partition function has to be | ||
calculated and then the expected particle number can be | ||
found. Introducing a new variable :math:`\xi = \epsilon - \mu`, and | ||
:math:`\beta` corresponding to the inverse temperature of the system. | ||
|
||
.. math:: | ||
\mathcal{Z} &= Tr(e^{-\beta \mathcal{H}}) = 1 + 2e^{-\beta\xi} + e^{-\beta(2\xi + U)} \\ | ||
\langle \hat{N} \rangle &= \frac{1}{\beta} \frac{\partial}{\partial \mu} \ln \mathcal{Z} | ||
""" | ||
|
||
# Code source: Óscar Nájera | ||
# License: BSD 3 clause | ||
|
||
import matplotlib.pylab as plt | ||
import numpy as np | ||
mu = np.linspace(0, 3, 800) | ||
for b in [10, 20, 30]: | ||
n = 2 * (np.exp(b * (mu - 1)) + np.exp(b * (2 * mu - 3))) / \ | ||
(1 + np.exp(b * (mu - 1)) * (2 + np.exp(b * (mu - 2)))) | ||
plt.plot(mu, n, label=r"$\beta={}$".format(b)) | ||
plt.xlabel(r'$\mu$ ($\epsilon=1$, $U=1$)') | ||
plt.ylabel(r'$\langle N \rangle=\langle n_\uparrow \rangle+\langle n_\downarrow\rangle$') | ||
plt.legend(loc=0) | ||
plt.show() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,12 @@ | |
Files that generate images should start with 'plot' | ||
|
||
""" | ||
# Don't use unicode_literals here (be explicit with u"..." instead) otherwise | ||
# tricky errors come up with exec(code_blocks, ...) calls | ||
from __future__ import division, print_function, absolute_import | ||
from time import time | ||
import ast | ||
import codecs | ||
import hashlib | ||
import os | ||
import re | ||
|
@@ -72,6 +75,7 @@ def prefixed_lines(): | |
basestring | ||
except NameError: | ||
basestring = str | ||
unicode = str | ||
|
||
|
||
############################################################################### | ||
|
@@ -93,6 +97,14 @@ def flush(self): | |
self.file2.flush() | ||
|
||
|
||
class MixedEncodingStringIO(StringIO): | ||
"""Helper when both ASCII and unicode strings will be written""" | ||
def write(self, data): | ||
if not isinstance(data, unicode): | ||
data = data.decode('utf-8') | ||
StringIO.write(self, data) | ||
|
||
|
||
############################################################################### | ||
CODE_DOWNLOAD = """**Total running time of the script:** | ||
({0:.0f} minutes {1:.3f} seconds)\n\n | ||
|
@@ -124,7 +136,8 @@ def flush(self): | |
""" | ||
|
||
|
||
CODE_OUTPUT = """.. rst-class:: sphx-glr-script-out | ||
# This one could contain unicode | ||
CODE_OUTPUT = u""".. rst-class:: sphx-glr-script-out | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We start using in our files, so we don't miss a string from __future__ import unicode_literals There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not quite sure what you mean. You mean in the modules you work on that
use sphinx-gallery you've started putting in a bunch of those lines? Or
you've started putting them in the sphinx-gallery code itself?
So far we haven't needed to use them to have unicode work properly. Does it
make them work better with sphinx-gallery, or is there some other
advantage?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unicode_literals takes the need away to prefix every string with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you try putting it in while on this branch, or on a previous one? It might work okay with this one since the unicode reading is a bit more unified. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I put in the |
||
|
||
Out:: | ||
|
||
|
@@ -143,7 +156,10 @@ def get_docstring_and_rest(filename): | |
rest: str | ||
`filename` content without the docstring | ||
""" | ||
with open(filename) as f: | ||
# can't use codecs.open(filename, 'r', 'utf-8') here b/c ast doesn't | ||
# seem to work with unicode strings in Python2.7 | ||
# "SyntaxError: encoding declaration in Unicode string" | ||
with open(filename, 'rb') as f: | ||
content = f.read() | ||
|
||
node = ast.parse(content) | ||
|
@@ -154,9 +170,11 @@ def get_docstring_and_rest(filename): | |
isinstance(node.body[0].value, ast.Str): | ||
docstring_node = node.body[0] | ||
docstring = docstring_node.value.s | ||
if hasattr(docstring, 'decode'): # python2.7 | ||
docstring = docstring.decode('utf-8') | ||
# This get the content of the file after the docstring last line | ||
# Note: 'maxsplit' argument is not a keyword argument in python2 | ||
rest = content.split('\n', docstring_node.lineno)[-1] | ||
rest = content.decode('utf-8').split('\n', docstring_node.lineno)[-1] | ||
return docstring, rest | ||
else: | ||
raise ValueError(('Could not find docstring in file "{0}". ' | ||
|
@@ -461,19 +479,22 @@ def execute_script(code_block, example_globals, image_path, fig_count, | |
# First cd in the original example dir, so that any file | ||
# created by the example get created in this directory | ||
os.chdir(os.path.dirname(src_file)) | ||
my_buffer = StringIO() | ||
my_buffer = MixedEncodingStringIO() | ||
my_stdout = Tee(sys.stdout, my_buffer) | ||
sys.stdout = my_stdout | ||
|
||
t_start = time() | ||
# don't use unicode_literals at the top of this file or you get | ||
# nasty errors here on Py2.7 | ||
exec(code_block, example_globals) | ||
time_elapsed = time() - t_start | ||
|
||
sys.stdout = orig_stdout | ||
|
||
my_stdout = my_buffer.getvalue().strip().expandtabs() | ||
# raise RuntimeError | ||
if my_stdout: | ||
stdout = CODE_OUTPUT.format(indent(my_stdout, ' ' * 4)) | ||
stdout = CODE_OUTPUT.format(indent(my_stdout, u' ' * 4)) | ||
os.chdir(cwd) | ||
figure_list = save_figures(image_path, fig_count, gallery_conf) | ||
|
||
|
@@ -491,6 +512,7 @@ def execute_script(code_block, example_globals, image_path, fig_count, | |
except Exception: | ||
formatted_exception = traceback.format_exc() | ||
|
||
sys.stdout = orig_stdout # need this here so these lines don't bomb | ||
print(80 * '_') | ||
print('%s is not compiling:' % src_file) | ||
print(formatted_exception) | ||
|
@@ -505,7 +527,8 @@ def execute_script(code_block, example_globals, image_path, fig_count, | |
fig_count += 1 # raise count to avoid overwriting image | ||
|
||
# Breaks build on first example error | ||
|
||
# XXX This check can break during testing e.g. if you uncomment the | ||
# `raise RuntimeError` by the `my_stdout` call, maybe use `.get()`? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lesteve here you go There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for this, we should probably fix it at one point. |
||
if gallery_conf['abort_on_example_error']: | ||
raise | ||
|
||
|
@@ -514,7 +537,7 @@ def execute_script(code_block, example_globals, image_path, fig_count, | |
sys.stdout = orig_stdout | ||
|
||
print(" - time elapsed : %.2g sec" % time_elapsed) | ||
code_output = "\n{0}\n\n{1}\n\n".format(image_list, stdout) | ||
code_output = u"\n{0}\n\n{1}\n\n".format(image_list, stdout) | ||
|
||
return code_output, time_elapsed, fig_count + len(figure_list) | ||
|
||
|
@@ -609,7 +632,8 @@ def generate_file_rst(fname, target_dir, src_dir, gallery_conf): | |
|
||
time_m, time_s = divmod(time_elapsed, 60) | ||
example_nb.save_file() | ||
with open(os.path.join(target_dir, base_image_name + '.rst'), 'w') as f: | ||
with codecs.open(os.path.join(target_dir, base_image_name + '.rst'), | ||
mode='w', encoding='utf-8') as f: | ||
example_rst += CODE_DOWNLOAD.format(time_m, time_s, fname, | ||
example_nb.file_name) | ||
f.write(example_rst) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also an orthogonal change, but was necessary to make the CIs happy...