```python
%%html
<!--Script block to left align Markdown Tables-->
<style>
  table {margin-left: 0 !important;}
</style>
```

<!--Script block to left align Markdown Tables-->
<style>
  table {margin-left: 0 !important;}
</style>

##### Notes

Leave script block above in place to left justify the table.
This problem can also be used as laboratory exercise in `matplotlib` lesson.
Dependencies: `matplotlib` and `math`; could also be solved using `numpy` and/or `pandas`

```python

```

```python

```

# Problem XX

Graphing Functions Special Functions

Consider the two functions listed below:

\begin{equation}
f(x) = e^{-\alpha x}
\label{eqn:fofx}
\end{equation}

\begin{equation}
g(x) = \gamma sin(\beta  x)
\label{eqn:gofx}
\end{equation}

Prepare a plot of the two functions on the same graph.

Use the values in Table below for $\alpha$, $\beta$, and $\gamma$.

|Parameter|Value|
|:---|---:|
|$\alpha$|0.50|
|$\beta$|3.00|
|$\gamma$|$\frac{\pi}{2}$|

The plot should have $x$ values ranging from $0$ to $10$ (inclusive) in sufficiently small increments to see curvature in the two functions as well as to identify the number and approximate locations of intersections. In this problem, intersections are locations in the $x-y$ plane where the two "curves" cross one another of the two plots.

```python
# By-hand evaluate f(x) for x=1, alpha = 1/2
```

```python
# By-hand evaluate g(x) for x=3.14, beta = 1/2, gamma = 2
```

```python
# Define the first function f(x,alpha), test the function using your by hand answer
```

```python
# Define the second function g(x,beta,gamma), test the function using your by hand answer
```

```python
# Built a list for x that ranges from 0 to 10, inclusive, with adjustable step sizes for plotting later on
```

```python
# Build a plotting function that plots both functions on the same chart
```

```python

```


```python
#we may need some code in the ../python directory and/or matplotlib styles
import sys
import os
sys.path.append('../python/')

#set up matplotlib
os.environ['MPLCONFIGDIR'] = '../mplstyles'
print(os.environ['MPLCONFIGDIR'])
import matplotlib as mpl
from matplotlib import pyplot as plt
#got smarter about the mpl config: see mplstyles/ directory
plt.style.use('standard')
print(mpl.__version__)
print(mpl.get_configdir())

#fonts
# Set the font dictionaries (for plot title and axis titles)
title_font = {'fontname':'Arial', 'size':'16', 'color':'black', 'weight':'normal',
              'verticalalignment':'bottom'} # Bottom vertical alignment for more space
axis_font = {'fontname':'Arial', 'size':'32'}
legend_font = {'fontname':'Arial', 'size':'22'}

#fonts global settings
mpl.rc('font',family=legend_font['fontname'])

#set up numpy
import numpy as np
```

    ../mplstyles
    3.0.3
    /home/phys/villaa/analysis/misc/nrFano_Constraint/mplstyles

# Summary

We know that the Dogherty paper [[Dough92][Dough92]] has measured the ionization variance for nuclear recoils in silicon. And that this paper has compared to results to the Lindhard description (J. Lindhard _et al_., Mat. Fys. Medd. K. Dan. Vidensk. Selsk **33**, 10 (1963)). The purpose of this note is to recast these results in terms of the effective Fano factor and make it clear where we got the information from, and how the data was processed.

[Dough92]: https://journals.aps.org/pra/abstract/10.1103/PhysRevA.45.2104 "Dougherty paper 1992"

# Extracting the Lindhard Function(s)

In the Lindhard reference above (J. Lindhard _et al_., Mat. Fys. Medd. K. Dan. Vidensk. Selsk **33**, 10 (1963)), Figure 8 contains the information we need and is reproduced below.

The red and green curves report the fractional variance $(\Omega/\epsilon)^2$ in phonon (heat) energy produced by a nucleus with a given initial non-dimensionalized energy $\epsilon$. From the `pdf` file for the publication listed we extracted the curves by first using `inkscape` to draw colored Bezier curves over the curves of interest and then extracting the `svg` points for those curves from the resulting saved `svg` figure.

For now instead of using the `svg` extraction, we are using `DataThief` to extract the colored curves. The results are shown below.

```python
import dataPython as dp
import numpy as np

lind_data0 = dp.getXYdata('data/lindhard2_OmegaepsD_fmt.txt')
lind_data1 = dp.getXYdata('data/lindhard2_OmegaepsE_fmt.txt')

lindD_e = np.asarray(lind_data0['xx'])
lindD = np.asarray(lind_data0['yy'])
lindE_e = np.asarray(lind_data1['xx'])
lindE = np.asarray(lind_data1['yy'])

print(np.min(np.diff(lindD_e)))
print(np.min(np.diff(lindE_e)))
```

    0.0
    0.0

```python
#set up a plot

fig,axes = plt.subplots(1,1,figsize=(9.0,8.0),sharex=True)
ax1 = axes

xmax=10

#ax1.errorbar(ddata_e,ddata_fluct,yerr=[ddata_fluct_err,ddata_fluct_err], marker='o', markersize=8, \
#             ecolor='k',color='k', linestyle='none', label='Dougherty Excess Fluctuation', linewidth=2)

#ax1.plot (X, diff, 'm-', label='Thomas-Fermi (newgrad)')
#ax1.plot (Esi(epr), 100*np.sqrt(f_Omega2_eta2(epr))*ylindv(1000*Esi(epr)), 'g-', label='$\Omega/\epsilon$ (NAC III approx. D)')
ax1.plot (lindD_e, np.sqrt(lindD)*100, 'g-', label='$\Omega/\epsilon$ (NAC III approx. D)')
ax1.plot (lindE_e, np.sqrt(lindE)*100, 'r-', label='$\Omega/\epsilon$ (NAC III approx. E)')

ax1.set_yscale('linear')
ax1.set_xscale('linear')
ax1.set_xlim(0.0, xmax)
ax1.set_ylim(0,10)
ax1.set_xlabel('non-dimensional energy ($\epsilon$)',**axis_font)
ax1.set_ylabel('$\Omega/\epsilon$ (%)',**axis_font)
#ax1.grid(True)
#ax1.xaxis.grid(True,which='minor',linestyle='--')
ax1.legend(loc=4,prop={'size':22})

for axis in ['top','bottom','left','right']:
  ax1.spines[axis].set_linewidth(2)

plt.tight_layout()
#plt.savefig('figures/figure.png')
plt.show()

```

The next thing to do is to convert the non-dimensional energy $\epsilon$ into the recoil energy for silicon. The equation to do this comes from the Lindhard reference (J. Lindhard _et al_., Mat. Fys. Medd. K. Dan. Vidensk. Selsk **33**, 10 (1963)).

\begin{equation}
E\,(\mathrm{keV}) = \frac{2\sqrt{2} \epsilon}{6.87758\times\mathrm{10}^{\mathrm{-2}}}
\end{equation}

```python
Esi = np.vectorize(lambda x: np.sqrt(2)*2*x/(6.87758e-5*1000))
```

We also need to translate the $\Omega/\epsilon$ into an effective Fano factor. Typically, for each event the non-dimensionalized ionization and phonon energy released are denoted $\eta$ and $\nu$ respectively. Since they add to $\epsilon$, we have:

\begin{equation}
\epsilon = \nu + \eta.
\end{equation}

This means that since $\Omega^2$ is the variance in $\nu$ it is also the variance in $\eta$. That means that the expression:

\begin{equation}
\frac{\Omega}{\eta}
\end{equation}

is equal to the fractional width of the ionization energy produced in the interaction. It is therefore equal to:

\begin{equation}
\frac{\sigma_N}{N},
\end{equation}

where N is the number of electron-hole pairs produced in an interaction. Since the effective Fano factor has $\sigma_N$ parameterized as $\sqrt{FN}$, we can use the above equality to find that:

\begin{equation}
F = N\left(\frac{\epsilon}{\eta}\right)^2\left(\frac{\Omega}{\epsilon} \right)^2.
\end{equation}

If we re-arrange using the ionization yeild as a function of recoil energy, $Y(E_r)$ we would get:

\begin{equation}
F = \frac{E_r}{\epsilon_{\gamma}Y(E_r)} \left(\frac{\Omega}{\epsilon}\right)^2.
\end{equation}

```python
#create a yield model
import lindhard as lind

#lindhard
lpar = lind.getLindhardPars('Si',True) #use the "calculated" value of k
print(lpar)
#ylind = lind.getLindhard(lpar)
ylind = lind.getLindhardSi_k(0.15)
ylindv = np.vectorize(ylind) #careful, this expects inputs in eV
```

    {'Z': 14, 'A': 28, 'k': 0.14600172346755985, 'a': 3.0, 'b': 0.15, 'c': 0.7, 'd': 0.6}

```python
#convert the vectors
epsg = 3.8e-3 #keV average energy per electron-hole pair created

F_D = Esi(lindD_e)*(1/(epsg*ylindv(1000*Esi(lindD_e))))*lindD
F_E = Esi(lindE_e)*(1/(epsg*ylindv(1000*Esi(lindE_e))))*lindE
```

```python
#set up a plot

fig,axes = plt.subplots(1,1,figsize=(9.0,8.0),sharex=True)
ax1 = axes

xmax=10

#ax1.errorbar(ddata_e,ddata_fluct,yerr=[ddata_fluct_err,ddata_fluct_err], marker='o', markersize=8, \
#             ecolor='k',color='k', linestyle='none', label='Dougherty Excess Fluctuation', linewidth=2)

#ax1.plot (X, diff, 'm-', label='Thomas-Fermi (newgrad)')
#ax1.plot (Esi(epr), 100*np.sqrt(f_Omega2_eta2(epr))*ylindv(1000*Esi(epr)), 'g-', label='$\Omega/\epsilon$ (NAC III approx. D)')
ax1.plot (Esi(lindD_e), F_D, 'g-', label='effective Fano (NAC III approx. D)')
ax1.plot (Esi(lindE_e), F_E, 'r-', label='effective Fano (NAC III approx. E)')

ax1.set_yscale('linear')
ax1.set_xscale('linear')
ax1.set_xlim(Esi(0), 150)
ax1.set_ylim(0,200)
ax1.set_xlabel('recoil energy ($E_r$) [keV]',**axis_font)
ax1.set_ylabel('effective Fano factor',**axis_font)
#ax1.grid(True)
#ax1.xaxis.grid(True,which='minor',linestyle='--')
ax1.legend(loc=4,prop={'size':22})

for axis in ['top','bottom','left','right']:
  ax1.spines[axis].set_linewidth(2)

plt.tight_layout()
#plt.savefig('figures/figure.png')
plt.show()
```

# Dougherty & Gerbier Data

The Dougherty publication [[Dough92][Dough92]] measures the apparent ionization variance in silicon by using neutron-scattering resonances to locate specific energies in the recoil spectrum which have a cross section shape change associated with the resonance. Events near those energies are measured by means of the induced charge the ionization propagation causes. Separate measurements of the instrumental noise for such a measurement allow the "extra" varaince to be isolated. This is presumed to come from uncertainty in the ionization production of a silicon recoil of a given energy.

The data in the publication was plot in comparison to the Lindhard predictions above, but not cast into the "effective Fano" language. Here we cast the measurements in terms of the "effective Fano" factor necessary to produce the variances observed.

[Dough92]: https://journals.aps.org/pra/abstract/10.1103/PhysRevA.45.2104 "Dougherty paper 1992"

In the Doughtery publication, the value quoted that is most directly related to the effective Fano fluctuation is the "excess fluctuation" in ionization energy. It is the 1$\sigma$ fluctuation in percent relative to the true silicon recoil energy. If we call this percent $p_e$, and the absolute 1$\sigma$ fluctuation as $\sigma_e$ then we have:

\begin{equation}
p_e = 100\cdot\frac{\sigma_e}{E_r}.
\end{equation}

And since we also have:

\begin{equation}
\sigma_e = \epsilon_{\gamma}^2F\bar{N},
\end{equation}

we can reconstruct the effective Fano factor, F as follows:

\begin{equation}
\begin{aligned}
F &= \frac{\sigma_e^2}{\epsilon_{\gamma}E_rY(E_r)}  \\
 &= \left(\frac{p_e}{100}\right)^2 \left(\frac{E_r}{\epsilon_{\gamma}Y(E_r)}\right),
\end{aligned}
\end{equation}

Where $Y(E_r)$ is the ionization yield and $\epsilon_{\gamma}$ is the average energy to create a single electron-hole pair in silicon.

The information from the Dougherty publication and the result of the effective Fano calculation above are given in the table below. Experimental uncertainties are quoted as values following the "$\pm$" symbol. The Observed width and Expected width are both in FWHM execpt for the 25.3 keV recoil energy point, which is quoted in half width at half max (HWHM). The excess fluctuation are given in 1$\sigma$.

Si recoil energy (keV)|Observed ionization (keV)|Lindhard shift (keV)|Ionization efficiency (%)|Observed width (keV)|Expected width (keV)|Excess fluct. (%)| effective Fano
:-|:-|:-|:-|:-|:-|:-|:-
109.1$\pm$0.7|55.5$\pm$2|0.55|51.4$\pm$2|16$\pm$3|3.5$\pm$0.4|6.1$\pm$1.2|208$\pm$82
75.7 $\pm$0.4|33.3$\pm$0.4|0.31+0.94|45.6$\pm$0.5|9.6$\pm$1.0|1.1$\pm$0.3|5.3$\pm$0.6|123$\pm$28
25.3$\pm$0.3|8.90$\pm$0.1|0.074|35.5$\pm$0.6|1.30$\pm$0.04|0.75$\pm$0.1|3.6$\pm$0.3|24.3$\pm$4.1
7.50$\pm$0.03|2.01$\pm$0.02|0.012|26.9$\pm$0.4|0.55$\pm$0.07|0.24$\pm$0.01|2.8$\pm$0.4|5.75$\pm$1.65
4.15$\pm$0.15|0.93$\pm$0.02|0.008|22.5$\pm$0.5|0.32$\pm$0.06|0.236$\pm$0.005|2.2$\pm$0.9|2.35$\pm$1.92

The Gerbier paper [[Gerb90][Gerb90]] measures ionization in silicon using the scattering of a nearly mono-energetic neutron beam. Similar calculations to the ones above can be used to extract the effective Fano factor except that the Gerbier experiment reports the absolute uncertainty in the ionization energy, as opposed to the fraction compared to the recoil energy.

Si recoil energy (keV)|Observed ionization (keV)|Ionization efficiency (%)|Observed width (eV)|Expected width (eV)|Excess fluct. (eV)| effective Fano
:-|:-|:-|:-|:-|:-|:-
21.7$\pm$0.2|8.79$\pm$0.08|40.7$\pm$0.5|1058$\pm$56|346$\pm$13|1000$\pm$59|29.80$\pm$17.11
19.5$\pm$0.2|7.56$\pm$0.11|38.7$\pm$0.7|1155$\pm$103|348$\pm$9|1101$\pm$108|42.27$\pm$8.33
13.5$\pm$0.3|4.53$\pm$0.06|33.6$\pm$0.7|680$\pm$37|317$\pm$11|601$\pm$42|20.96$\pm$2.96
8.6$\pm$0.1|2.66$\pm$0.02|31.1$\pm$0.5|411$\pm$11|218$\pm$6|348$\pm$13|11.91$\pm$0.91
4.7$\pm$0.1|1.25$\pm$0.03|26.6$\pm$0.8|266$\pm$25|191$\pm$5|185$\pm$36|7.20$\pm$2.81
4.15$\pm$0.1|1.14$\pm$0.02|27.4$\pm$0.8|253$\pm$25|190$\pm$5|166$\pm$39|6.38$\pm$3.00
3.9$\pm$0.1|0.89$\pm$0.08|22.9$\pm$2.0|304$\pm$52|185$\pm$5|241$\pm$66|17.11$\pm$9.49
3.3$\pm$0.1|0.85$\pm$0.05|25.9$\pm$1.6|227$\pm$32|186$\pm$5|131$\pm$55|5.28$\pm$4.45

[Gerb90]: https://journals.aps.org/prd/abstract/10.1103/PhysRevD.42.3211 "Gerbier paper 1990"

```python
#get Dougherty and Gerbier Data
ddataY = dp.getXYdata_wXYerr('data/Dougherty_Yield.txt')
ddataFluct = dp.getXYdata_wXYerr('data/Dougherty_Fluct.txt')

ddataY_G = dp.getXYdata_wXYerr('data/Gerbier_Yield.txt')
ddataFluct_G = dp.getXYdata_wXYerr('data/Gerbier_Fluct.txt')

#convert to numpy arrays
ddata_e = np.asarray(ddataFluct['xx'])
ddata_fluct = np.asarray(ddataFluct['yy'])
ddata_fluct_err = np.asarray(ddataFluct['ey'])

ddata_Y = np.asarray(ddataY['yy'])
ddata_Y_err = np.asarray(ddataY['ey'])

ddataG_e = np.asarray(ddataFluct_G['xx'])
ddataG_fluct = np.asarray(ddataFluct_G['yy'])/1000
ddataG_fluct_err = np.asarray(ddataFluct_G['ey'])/1000

ddataG_Y = np.asarray(ddataY_G['yy'])
ddataG_Y_err = np.asarray(ddataY_G['ey'])

epsg = 3.8e-3 #epsilon-gamma for silicon in keV per pair
ddata_fluct_F = (ddata_fluct/100)**2 * (ddata_e/(epsg*(ddata_Y/100)))
#ddata_fluct_F_err = (ddata_fluct_err/100)**2 * (ddata_e/(epsg*(ddata_Y/100)))
ddata_fluct_F_err = np.sqrt(((ddata_fluct/100)*(2*ddata_e/(epsg*(ddata_Y/100))))**2*(ddata_fluct_err/100)**2 \
                           +((ddata_fluct/100)**2*(ddata_e/(epsg*(ddata_Y/100)**2)))**2*(ddata_Y_err/100)**2 )
#print(ddata_fluct_F_err)
ddata_fluct_F_err_A = np.sqrt(((ddata_fluct/100)*(2*ddata_e/(epsg*(ddata_Y/100))))**2*(ddata_fluct_err/100)**2)
ddata_fluct_F_err_B = np.sqrt(((ddata_fluct/100)**2*(ddata_e/(epsg*(ddata_Y/100)**2)))**2*(ddata_Y_err/100)**2 )
ddata_fluct_F_err = np.sqrt(ddata_fluct_F_err_A**2 + ddata_fluct_F_err_B**2)

ddata_fluct_F_G = (ddataG_fluct/ddataG_e)**2 * (ddataG_e/(epsg*(ddataG_Y/100)))
#ddata_fluct_F_err = (ddata_fluct_err/100)**2 * (ddata_e/(epsg*(ddata_Y/100)))
ddata_fluct_F_err_G = np.sqrt(((ddataG_fluct/ddataG_e)*(2*ddataG_e/(epsg*(ddataG_Y/100))))**2*(ddataG_fluct_err/ddataG_e)**2 \
                           +((ddataG_fluct/ddataG_e)**2*(ddataG_e/(epsg*(ddataG_Y/100)**2)))**2*(ddataG_Y_err/100)**2 )

ddata_fluct_F_err_G_A = np.sqrt(((ddataG_fluct/ddataG_e)*(2*ddataG_e/(epsg*(ddataG_Y/100))))**2*(ddataG_fluct_err/ddataG_e)**2)
ddata_fluct_F_err_G_B = np.sqrt(((ddataG_fluct/ddataG_e)**2*(ddataG_e/(epsg*(ddataG_Y/100)**2)))**2*(ddataG_Y_err/100)**2 )
ddata_fluct_F_err_G = np.sqrt(ddata_fluct_F_err_G_A**2 + ddata_fluct_F_err_G_B**2)

print(ddata_e)
print(ddata_fluct_F)
print(ddata_fluct_F_err)
print(ddataG_e)
print(ddata_fluct_F_G)
print(ddata_fluct_F_err_G)
```

    [109.1   75.7   25.3    7.5    4.15]
    [207.84410199 122.71543167  24.30600445   5.75229896   2.34923977]
    [82.17366352 27.81718869  4.07177705  1.64573833  1.92281409]
    [21.7  19.5  13.5   8.6   4.7   4.15  3.9   3.3 ]
    [29.79629465 42.27128645 20.95522371 11.91560371  7.2041105   6.37725701
     17.11395553  5.28378686]
    [3.53496608 8.32817692 2.96120797 0.91062459 2.81212102 3.00232178
     9.49203685 4.44875839]

```python
#set up a plot
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
fig,axes = plt.subplots(1,1,figsize=(9.0,8.0),sharex=True)
ax1 = axes

xmax=10

ax1.errorbar(ddata_e,ddata_fluct_F,yerr=[ddata_fluct_F_err,ddata_fluct_F_err], marker='o', markersize=8, \
             ecolor='k',color='k', linestyle='none', label='Dougherty eff. F', linewidth=2)
ax1.errorbar(ddataG_e,ddata_fluct_F_G,yerr=[ddata_fluct_F_err_G,ddata_fluct_F_err_G], marker='^', markersize=8, \
             ecolor='k',color='k', linestyle='none', label='Gerbier eff. F', linewidth=2)

#ax1.plot (X, diff, 'm-', label='Thomas-Fermi (newgrad)')
#ax1.plot (Esi(epr), 100*np.sqrt(f_Omega2_eta2(epr))*ylindv(1000*Esi(epr)), 'g-', label='$\Omega/\epsilon$ (NAC III approx. D)')
ax1.plot (Esi(lindD_e), F_D, 'k-', label='eff. F (Lind. approx. D)')
ax1.plot (Esi(lindE_e), F_E, 'k--', label='eff. F (Lind. approx. E)')

ax1.set_yscale('linear')
ax1.set_xscale('linear')
ax1.set_xlim(Esi(0), 150)
ax1.set_ylim(0.1,300)
ax1.set_xlabel('recoil energy ($E_r$) [keV]',**axis_font)
ax1.set_ylabel('effective Fano factor',**axis_font)
#ax1.grid(True)
#ax1.xaxis.grid(True,which='minor',linestyle='--')
ax1.legend(loc=4,prop={'size':22})

###Make inset
bbox_ll_x = 0.07
bbox_ll_y = -0.0225
bbox_w = 1
bbox_h = 1
eps = 0.01
axins = inset_axes(ax1, height="35%", width="55%", bbox_to_anchor=(bbox_ll_x,bbox_ll_y,bbox_w-bbox_ll_x,bbox_h), loc='upper left',bbox_transform=ax1.transAxes)
#ax1.add_patch(plt.Rectangle((bbox_ll_x, bbox_ll_y+eps), bbox_w-eps-bbox_ll_x, bbox_h-eps, ls="--", ec="c", fc="None",
#                           transform=ax1.transAxes))

#axins = plt.axes([0,0,1,1])
#axins_pos = InsetPosition(ax3, [0.25, 0.65, 0.7, 0.3])
#axins.set_axes_locator(axins_pos)

# larger region than the original image
x1, x2, y1, y2 = 0, 10, 0, 20
axins.set_xlim(x1, x2)
axins.set_ylim(y1, y2)

axins.errorbar(ddata_e,ddata_fluct_F,yerr=[ddata_fluct_F_err,ddata_fluct_F_err], marker='o', markersize=8, \
             ecolor='k',color='k', linestyle='none', label='', linewidth=2)
axins.errorbar(ddataG_e,ddata_fluct_F_G,yerr=[ddata_fluct_F_err_G,ddata_fluct_F_err_G], marker='^', markersize=8, \
             ecolor='k',color='k', linestyle='none', label='', linewidth=2)
axins.plot (Esi(lindD_e), F_D, 'k-', label='')
axins.plot (Esi(lindE_e), F_E, 'k--', label='')

axins.yaxis.grid(True,which='minor',linestyle='--')
axins.xaxis.grid(True,which='minor',linestyle='--')
axins.grid(True)
####

for axis in ['top','bottom','left','right']:
  ax1.spines[axis].set_linewidth(2)

#plt.tight_layout()
#plt.savefig('figures/figure.png')
plt.show()
```

```python

```


# Computationally Visualizing Crystals Pt. 2
### Christina C. Lee

### Category: General Audience

### Crystals Series
* [Fundamental Crystal Shapes](../General/Crystal-Shapes.ipynb)
* [MultiSite Unit Cells](../General/MultiSite-Unit-Cells.ipynb)

Time to one-up the Bravais lattice from Part 1.  Many beautiful lattices don't adhere to the "every site the same" policy.  They still repeat, but just take a little bit longer to get around to doing so.

Take the Kagome Lattice, named for the Japanese style of basket weaving, below,

 Wikimedia commons

If we look at the stars at the center of triangles, we can recognize a point triangular Bravais lattice.  Now each of those stars stands for a grouping of three sites in a Unit Cell.  According to Chem Wiki, a unit cell is:
>A unit cell is the most basic and least volume consuming repeating structure of any solid. It is used to visually simplify the crystalline patterns solids arrange themselves in.

Now I chose these triangles to be be the unit cells above and in my computational representation below, but can you think of any other ways to represent the unit cell?

Turns out, there isn't a unique way.  We can go further and define the Wigner-Seitz unit cell, which uses the Bravais translations to pick out just ONE of the various possible definitions.

In my line of work though, we often use either the easiest to write down, or the one that has the symmetries we want.

### Introducing Some Lattice Options

You saw Kagome above.

The options I've put in now are:
* 2D
  * honeycomb
  * kagome
  * shuriken aka しゅりけん, 手裏剣, or Square-Kagome
* 3D
  * diamond
  * pyrochlore

The ones implemented here, except for diamond, are frustrated lattices that I work with in my research. Honeycomb is well known in condensed matter physics for being the structure of graphene, an extremely important material right now, though I work with it in terms of the Kitaev spin model.  Kagome and Pyrochlore are also popular models within my community.  The shuriken lattice is more uncommon, but gaining ground in the frustration community.

####  Japanese Shurikens- a type of ninja fighting star

 By kaex0r (http://www.flickr.com/photos/kaex0r414/191765028/) [CC BY 2.0 (http://creativecommons.org/licenses/by/2.0)], via Wikimedia Commons

```julia
# importing our packages
using Plots
gr()
```

    Plots.GRBackend()

```julia
lattice="shuriken";

Nx=3;
Ny=3;
Nz=1;
```

```julia
# A cell to just evaluate
# This one sets the unit vectors (a,b,c) for the different unit cells
# Can you guess what a lattice will look like by looking at the vectors?
if(lattice=="honeycomb") #also the graphite lattice
    d=2;
    Ncell=2;
    unit=[[0 0 0]
        [cos(π/6) sin(π/6) 0]];
    a=[sqrt(3),0,0];
    b=[sqrt(3)/2,3/2,0];
    c=[0,0,1];
elseif(lattice=="kagome" || lattice=="かごめ")
    d=2;
    Ncell=3;
    unit=[[0 0 0]
          [1 0 0]
        [.5 sqrt(3)/2 0]];
    a=[2,0,0];       #Look familiar? Checkout pt from Pt. 1
    b=[1, sqrt(3), 0];
    c=[0,0,1];
elseif(lattice=="shuriken"|| lattice=="しゅりけん" || lattice=="手裏剣")
    d=2;
    Ncell=6;
    unit=[[0 0 0]
          [.5 0 0]
          [0 .5 0]
          [.5 .5 0]
        [.5+.25*sqrt(3) .25 0]
        [.25 .5+.25*sqrt(3) 0]];
    a=[.5+.5*sqrt(3),0,0];
    b=[0,.5+.5*sqrt(3),0];
    c=[0,0,1];
elseif(lattice=="diamond")
    d=3;
    Ncell=2;
    unit=[[0 0 0]
          [.25 .25 .25]];
    a=[.5,.5,0];    #Look familiar? Checkout fcc from Pt.1
    b=[.5,0,.5];
    c=[0,.5,.5];
elseif(lattice=="pyrochlore")
    d=3;
    Ncell=4;
    unit=[[0 0 0]
        [.25 .25 0]
        [.25 0 .25]
        [0 .25 .25]];
    a=[.5,.5,0];
    b=[.5,0,.5];
    c=[0,.5,.5];

else
    println("Please have a correct lattice")
end
"Cell finished"
```

    "Cell finished"

### Connections to Bravais Lattices

If you look at some of the comments above, and checkout the basis vectors from Crystal Shapes, like pt,
        \begin{equation}
            a=[1,0,0]\;\;\;\;\;\;\;\;\; b=[.5,\frac{\sqrt{3}}{2},0],
        \end{equation}
you'll notice they're the same except for a scaling factor.  This has to be true, since only 14 different patterns tile 3D space uniquely.

```julia
# Another cell to just evaluate
# Here we set up some numbers and matrices for our computation
N=Nx*Ny*Nz*Ncell;    #The total number of sites
aM=transpose(repeat(a,outer=[1,Ncell]));
bM=transpose(repeat(b,outer=[1,Ncell*Nx])); #these allow us to copy an entire row or layer at once
cM=transpose(repeat(c,outer=[1,Ncell*Nx*Ny]));

X=Array{Float64}(undef,N,3);  #where we store the positions
"Cell finished"
```

    "Cell finished"

```julia
# Another cell to just evaluate
# Here we are actually calculating the positions for every site
for i in 1:Nx    #for the first row
    X[Ncell*i-Ncell+1:Ncell*i,:]=unit.+(i-1)*aM;
end

for j in 2:Ny    #copying the first row into the first layer
    X[Ncell*Nx*(j-1).+(1:Ncell*Nx),:]=X[1:Ncell*Nx,:].+(j-1)*bM;
end

for j in 2:Nz    #copying the first layer into the entire cube
    X[Ncell*Ny*Nx*(j-1).+(1:Ncell*Nx*Ny),:]=X[1:Ncell*Nx*Ny,:].+(j-1)*cM;
end
"Cell finished"
```

    "Cell finished"

```julia
scatter(X[:,1],X[:,2])
# scatter(X[:,1],X[:,2],X[:,3])
plot!(title=lattice,xlabel="X",ylabel="Y",zlabel="Z",legend=false)
```

### Perdy Pictures
From these plots, some 3D structures like the pyrochlore are hard to visualize.  So here's a nice graphic I made that might help a little bit more.
####  Pyrochlore

The honeycomb, like several other lattices you see around here, is bipartite.  You can see in my image that black sites are only next to white sites, and vice versa.  This property can make the system much easier to work with.

If you keep reading, Please Do!, these lattices will keep cropping up again and again.  I'll probably throw in some new ones as well.

Anyway, if you've had too many lattices, will move onto some Quantum Mechanics to look at atomic orbitals soon!

```julia

```


\title{(some) LaTeX environments \par for Jupyter notebook}
\author{@jfbercher}
\maketitle

# Introduction

This extension for IPython 4.x or Jupyter enables to use some LaTeX commands and environments in the notebook's markdown cells.
\begin{enumerate}
\item **LaTeX commands and environments**
\begin{itemize}
\item support for some LaTeX commands within markdown cells, *e.g.* `\textit`, `\textbf`, `\underline`, `author`, `\title`, LaTeX comments
\item support for **theorems-like environments**, support for labels and **cross references**
\item support for **lists**: *enumerate, itemize*,
\item limited support for a **figure environment**,
\item support for an environment *listing*,
\item additional *textboxa* environment
\end{itemize}
\item **Citations and bibliography**
\begin{itemize}
\item support for `\cite` with creation of a References section
\end{itemize}
\item it is possible mix markdown and LaTeX markup
\item **Document-wide numbering of equations and environments, support for `\label` and `\ref`**
\item **Configuration toolbar**
\item **LaTeX_envs dropdown menu for a quick insertion of environments**
\item Support for **User $\LaTeX$ definitions file**
\item Environments title/numbering can be customized by users in ``user_envs.json`` config file
\item **Export to HTML and LaTeX with a customized exporter**
\item Styles can be customized in the `latex_env.css` stylesheet
\item Limited **autocompletion** for \$, (, {, [
\end{enumerate}

A simple illustration is as follows: one can type the following in a markdown cell
\begin{listing}
The dot-product is defined by equation (\ref{eq:dotp}) in theorem \ref{theo:dotp} just below:
\begin{theorem}[Dot Product] \label{theo:dotp}
Let $u$ and $v$ be two vectors of $\mathbb{R}^n$. The dot product can be expressed as
\begin{equation}
\label{eq:dotp}
u^Tv = |u||v| \cos \theta,
\end{equation}
where $\theta$ is the angle between $u$ and $v$ ...
\end{theorem}
\end{listing}
and have it rendered as

The dot-product is defined by equation (\ref{eq:dotp}) in theorem \ref{theo:dotp} just below:
\begin{theorem}[Dot Product] \label{theo:dotp}
Let $u$ and $v$ be two vectors of $\mathbb{R}^n$. The dot product can be expressed as
\begin{equation}
\label{eq:dotp}
u^Tv = |u||v| \cos \theta,
\end{equation}
where $\theta$ is the angle between $u$ and $v$ ...
\end{theorem}

## ** What's new **

**February 9, 2017** - version 1.3.7

- Enable customizing hotkeys for inserting environments (via `nbextensions_configurator`)
- LaTeX\_envs menu can be customized by editing `envsLatex.json` in `nbextensions/latex_envs` directory)
- Autocompletion for \$,(,{,[
- Updates to ensure compatibility with nbTranslate
- Recognize \\ [..\\ ] and \\ (..\\ ) as LaTeX equations delimiters in nb

**November 2, 2016** - version 1.3.1

- Support for **user environments configuration** file (`user_envs.json` in `nbextensions/latex\_envs` directory). This file is included by the html export template.
- Support for **book/report style numbering** of environments, e.g. "Example 4.2" is example 2 in section 4.
- Support for `\author`, `\title`, and `maketitle`. Author and title are saved in notebook metadata, used in html/latex exports. The maketitle command also formats a title in the LiveNotebook.
- Added a Toogle menu in the config toolbar to:
    - toggle use of user's environments config file
    - toggle `report-style` numbering

**September 18, 2016** - version 1.3

- Support for **user personal LaTeX definitions** file (`latexdefs.tex` in current directory). This file is included by the html and latex export templates.
- Style for nested enumerate environments added in `latex_envs.css`
- Added a Toogle menu in the config toolbar to:
    - toggle the display of the LaTeX_envs dropdown menu,
    - toggle the display of labels keys,
    - toggle use of user's LaTeX definition file
- **Cross references now use the true environment number instead of the reference//label key**. **References are updated immediately**. This works **document wide** and works for pre and post references
- Support for optional parameters in theorem-like environments
- Support for spacings in textmode, eg `\par`, `\vspace, \hspace`
- Support for LaTeX comments % in markdown cells
- Reworked loading and merging of system/document configuration parameters

**August 28, 2016** - version 1.2

- **Added support for nested environments of the same type**. Nesting environments of different type was already possible, but there was a limitation for nesting environments of the same kind; eg itemize in itemize in itemize. This was due to to the fact that regular expressions are not suited to recursivity. I have developped a series of functions that enable to extract nested environments and thus cope with such situations.

- Corrected various issues, eg [#731](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/issues/731), [#720](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/issues/720) where the content of nested environments was incorrectly converted to markdown.

- Completely reworked the configuration toolbar. Re-added tips.
- Added a toggle-button for the LaTeX\_envs menu
- Added system parameters that can be specified using the [nbextensions_configurator](https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator/tree/master/src/jupyter_nbextensions_configurator/static/nbextensions_configurator). Thus reworked the configuration loading/saving.
- Reworked extension loading. It now detects if the notebook is fully loaded before loading itself.

**August 03, 2016** - version 1.13

- Added a template to also keep the toc2 features when exporting to html:
```
jupyter nbconvert --to html_toclenvs FILE.ipynb
```
- Added a dropdown menu that enables to insert all main LaTeX\_envs environments using a simple click. Two keybards shortcuts (Ctrl-E and Ctrl-I) for equations and itemize are also provided. More environments and shortcuts can be added in the file `envsLatex.js`.

- Added a link in the general help menu that points to the documentation.

**July 27, 2016** - version 1.1

- In this version I have reworked **equation numbering**. In the previous version, I used a specialized counter and detected equations rendering for updating this counter. Meanwhile, this feature has been introduced in `MathJax` and now we rely on MathJax implementation. rendering is significantly faster. We still have keep the capability of displaying only equation labels (instead of numbers). The numbering is automatically updated and is document-wide.
- I have completely reworked the **notebook conversion** to plain $\LaTeX$ and html. We provide specialized exporters, pre and post processors, templates. We also added entry-points to simplify the conversion process. It is now as simple as
```bash
jupyter nbconvert --to html_with_lenvs FILE.ipynb
```
to convert `FILE.ipynb` into html while keeping all the features of the `latex_envs` notebook extension in the converted version.

# Main features
## Implementation principle

The main idea is to override the standard Markdown renderer in order to add a *small* parsing of LaTeX expressions and environments. This heavily uses regular expressions. The LaTeX expression are then rendered using an html version. For instance `\underline {something}` is rendered as `<u> something </u>`, that is \underline{something}. The environments are replaced by an html tag with a class derived from the name of the environment. For example, a `definition` denvronment will be replaced by an html rendering corresponding to the class `latex_definition`. The styles associated with the different classes are specified in `latex_env.css`. These substitutions are implemented in `thsInNb4.js`.

## Support for simple LaTeX commands

We also added some LaTeX commands (e.g. `\textit`, `\textbf`, `\underline`) -- this is useful in the case of copy-paste from a LaTeX document. The extension also supports some textmode spacings, namely `\par`, `\vspace, \hspace` as well as `\title`, `\author`, `maketitle` and  LaTeX comments % in markdown cells. Labels and cross-references are supported, including for equations.

## Available environments

- **theorems-like environments**: *property, theorem, lemma, corollary, proposition, definition,remark, problem,           exercise, example*,
- **lists**: *enumerate, itemize*,
- limited support for a *figure* environment,
- an environment *listing*,
- *textboxa*, wich is a `textbox` environment defined as a demonstration (see below).

More environments can be added easily in the user\_envs config file `user_envs.json` or directly in the javascript source file `thmsInNb4.js`. The rendering is done according to the stylesheet `latex_env.css`, which can be customized.
\begin{remark}
When exporting to html, the `latex_env.css` file honored is the file on the github CDN. However, customized css can be added in a `custom.css` file that must reside in the same directory as the notebook itself. The reason for that is that the `css` file must be in the same directory as the notebook file for inclusion, which means copying it in each working directory. As the rendering of the html file obtained is done using the original javascript code, the same is true for the source files; therefore it is better to curstomize environments in  `user_envs.json` which is taken into account when exporting to html.
\end{remark}

## Automatic numerotation, labels and references

Several counters for numerotation are implemented: counters for         problem, exercise, example, property, theorem, lemma, corollary, proposition, definition, remark, and figure are available.
Mathjax-equations with a label are also numbered document-wide.
An anchor is created for any label which enables to links things within the document: `\label` and `\ref` are both supported. A limitation was that numbering was updated (incremented) each time a cell is rendered. Document-wide automatic updating is implemented since version 1.3. A toolbar button is provided to reset the counters and refresh the rendering of the whole document (this is still useful for citations and bibliography refresh).

\label{example:mixing} A simple example is as follows, featuring automatic numerotation, and the use of labels and references. Also note that standard markdown can be present in the environment and is interpreted.
*The rendering is done according to the stylesheet `latex_env.css`, which of course, can be customized to specific uses and tastes*.

\begin{listing}
\begin{definition} \label{def:FT}
Let $x[n]$ be a sequence of length $N$. Then, its **Fourier transform** is given by
\begin{equation}
\label{eq:FT}
X[k]= \frac{1}{N} \sum_{n=0}^{N-1} x[n] e^{-j2\pi \frac{kn}{N}}
\end{equation}
\end{definition}
\end{listing}

\begin{definition} \label{def:FT}
Let $x[n]$ be a sequence of length $N$. Then, its **Fourier transform** is given by
\begin{equation}
\label{eq:FT2}
X[k]= \frac{1}{N} \sum_{n=0}^{N-1} x[n] e^{-j2\pi \frac{kn}{N}}
\end{equation}
\end{definition}

It is now possible to refer to the definition and to the equation by their labels,  as in:
\begin{listing}
As an example of Definition \ref{def:FT}, consider the Fourier transform (\ref{eq:FT2}) of a pure cosine wave given by
$$
x[n]= \cos(2\pi k_0 n/N),
$$
where $k_0$ is an integer.
\end{listing}

As an example of Definition \ref{def:FT}, consider the Fourier transform (\ref{eq:FT2}) of a pure cosine wave given by
$$
x[n]= \cos(2\pi k_0 n/N),
$$
where $k_0$ is an integer.
Its Fourier transform is given by
$$
X[k] = \frac{1}{2} \left( \delta[k-k_0] + \delta[k-k_0] \right),
$$
modulo $N$.

## Bibliography

### Usage

It is possible to cite bibliographic references using the standard LaTeX `\cite` mechanism. The extension looks for the references in a bibTeX file, by default `biblio.bib` in the same directory as the notebook. The name of this file can be modified in the configuration toolbar. It is then possible to cite works in the notebook, e.g.
\begin{listing}
The main paper on IPython is definitively \cite{PER-GRA:2007}. Other interesting references are certainly \cite{mckinney2012python, rossant2013learning}. Interestingly, a presentation of the IPython notebook has also be published recently in Nature \cite{shen2014interactive}.
\end{listing}
The main paper on IPython is definitively \cite{PER-GRA:2007}. Other interesting references are certainly \cite{mckinney2012python, rossant2013learning}. Interestingly, a presentation of the IPython notebook has also be published recently in Nature \cite{shen2014interactive}.

### Implementation

The implemention uses several snippets from the nice [icalico-document-tools](https://bitbucket.org/ipre/calico/downloads/) extension that also considers the rendering of citations in the notebook. We also use a modified version of the [bibtex-js](https://code.google.com/p/bibtex-js/) parser for reading the references in the bibTeX file. The different functions are implemented in `bibInNb4.js`. The rendering of citations calls can adopt three styles (Numbered, by key or apa-like) -- this can be selected in the configuration toolbar. It is also possible to customize the rendering of references in the reference list. A citation template is provided in the beginning of file `latex_envs.js`:
```
var cit_tpl = {
// feel free to add more types and customize the templates
    'INPROCEEDINGS': '%AUTHOR:InitialsGiven%, ``_%TITLE%_\'\', %BOOKTITLE%, %MONTH% %YEAR%.',
    ... etc
```
The keys are the main types of documents, eg inproceedings, article, inbook, etc. To each key is associated a string where the %KEYWORDS% are the fields of the bibtex entry. The keywords are replaced by the correponding bibtex entry value. The template string can formatted with additional words and effects (markdown or LaTeX are commands are supported)

## Figure environment

Finally, it is sometimes useful to integrate a figure within a markdown cell. The standard markdown markup for that is ``, but a limitation is that the image can not be resized, can not be referenced and is not numbered. Furthermore it can be useful for re-using existing code. Threfore we have added a limited support for the `figure` environment. This enables to do something like
\begin{listing}
\begin{figure}
\centerline{\includegraphics[width=10cm]{example.png}}
\caption{\label{fig:example} This is an example of figure included using LaTeX commands.}
\end{figure}
\end{listing}
which renders as
\begin{figure}
\centerline{\includegraphics[width=10cm]{example.png}}
\caption{\label{fig:example} This is an example of figure included using LaTeX commands.}
\end{figure}
Of course, this Figure can now be referenced:
\begin{listing}
Figure \ref{fig:example} shows a second filter with input $X_2$, output $Y_2$  and an impulse response denoted as $h_2(n)$
\end{listing}
Figure \ref{fig:example} shows a second filter with input $X_2$, output $Y_2$  and an impulse response denoted as $h_2(n)$

## figcaption

For Python users, we have added in passing a simple function in the `latex_envs.py` library.

This function can be imported classically, eg `from latex_envs.latex_envs import figcaption` (or `from jupyter_contrib_nbextensions.nbconvert_support.latex_envs import figcaption` if you installed from the jupyter_contrib repo).

Then, this function enables to specify a caption and a label for the next plot. In turn, when exporting to $\LaTeX$, the corresponding plot is converted to a nice figure environement with a label and a caption.

```python
%matplotlib inline
import matplotlib.pyplot as plt
from jupyter_contrib_nbextensions.nbconvert_support.latex_envs import figcaption
from numpy import pi, sin, arange
figcaption("This is a nice sine wave", label="fig:mysin")
plt.plot(sin(2*pi*0.01*arange(100)))
```

## Other features

- As shown in the examples, eg \ref{example:mixing} (or just below), **it is possible to mix LaTeX and markdown markup in environments**
- Support for **line-comments**: lines beginning with a % will be masked when rendering
- Support for **linebreaks**: `\par_`, where \_ denotes any space, tab, linefeed, cr, is replaced by a linebreak

- Environments can be nested. egg:
\begin{listing}
This is an example of nested environments, with equations inside\\
\begin{proof} Demo
% This is a comment
\begin{enumerate}
\item $$ \left\{ p_1, p_2, p_3 \ldots p_n \right\} $$
\item A **nested enumerate**
\item second item
\begin{enumerate}
\item $ \left\{ p_1, p_2, p_3 \ldots p_n \right\} $
\item And *another one*
\item second item
\begin{enumerate}
\item $$ \left\{ p_1, p_2, p_3 \ldots p_n \right\} $$
\item second item
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{proof}
\end{listing}
which results in

This is an example of nested environments, with equations inside\\
\begin{proof} Demo
% This is a comment
\begin{enumerate}
\item
\begin{equation}\label{eq:}
\left\{ p_1, p_2, p_3 \ldots p_n \right\}
\end{equation}
$$ \left\{ p_1, p_2, p_3 \ldots p_n \right\} $$
\item A **nested enumerate**
\item second item
\begin{enumerate}
\item $\left\{ p_1, p_2, p_3 \ldots p_n \right\}$
\item And *another one*
\item second item
\begin{enumerate}
\item $$ \left\{ p_1, p_2, p_3 \ldots p_n \right\} $$
\item second item
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{proof}

## User interface

### Buttons on main toolbar

On the main toolbar, the extension provides three buttons  The first one can be used to refresh the numerotation of equations and references in all the document. The second one fires the reading of the bibliography bibtex file and creates (or updates) the reference section. Finally the third one is a toogle button that opens or closes the configuration toolbar.

### Configuration toolbar

The configuration toolbar   enables to enter some configuration options for the extension.

First, the `LaTeX\_envs` title links to this documentation. Then, the bibliography text input can be used to indicate the name of the bibtex file. If this file is not found and the user creates the reference section, then this section will indicate that the file was not found. The `References` drop-down menu enables to choose the type of reference calls. The Equations input box enables to initiate numbering of equations at the given number (this may be useful for complex documents in several files/parts). The `Equations` drop-down menu let the user choose to number equation or to display their label instead. The two next buttons enable to toogle display of the LaTeX\_envs environments insertion menu or to toggle the displau of LaTeX labels. Finally The `Toogles` dropdown menu enable to toogle the state of several parameters. All these configuration options are then stored in the notebook's metadata (and restored on reload).

The `Toggles` dropdown menu

enables to toggle the state of several configuration options:

- display the `LaTeX_envs` insertion menu or not,
- show labels anchors,
- use $\LaTeX$ user own LaTeX defintions (loads `latexdefs.tex` file from current document directory),
- load user's environments configuration (file `user_envs.json` in `nbextensions/latex_envs` directory),
- select "report style" numbering of environments

### The `LaTeX_envs` insertion menu
The `LaTeX_envs` insertion menu

enables a quick insertion of LaTeX environments, some with a keyboard shorcut (this can be customized in `envsLatex.js`). Besides, selected text will be inserted in the environment.

# Conversion to LaTeX and HTML

The extension works in the live-notebook. Since it relies on a bunch of javascript, the notebook does not render as is in services such as `nbviewer` or `github` viewer. Similarly, `nbconvert` does not know of the LaTeX constructs which are used here and therefore does not fully convert notebooks using this extension.

Therefore, we provide specialized templates and exporters to achieve these conversions.

## Conversion to html
We provide a template `latex_envs.tpl` and an exporter class `LenvsHTMLExporter` (in library `latex_envs.py`). Using that class, conversion simply amounts to
```
jupyter nbconvert --to latex_envs.LenvsHTMLExporter FILE.ipynb
```
A shortcut is also provided
```
jupyter nbconvert --to html_with_lenvs FILE.ipynb
```
It should be noted that the rendering is done exactly in the same way as in the livenotebook. Actually, it is the very same javascript which is run in the html file. The javascript functions are available on the extension github as well as in the `jupyter_notebook_extensions` CDN, which means that the rendering of the html files requires an internet connection (this is also true for the rendering of equations with MathJax).

Another template `latex_envs_toc.tpl` is provided which enables to also
keep the toc2 features when exporting to html (*it even works if you do not have the `toc2` extension!*):
```bash
jupyter nbconvert --to html_with_toclenvs FILE.ipynb
```
**If you use the version included in the jupyter_notebook_extensions collection**, the entry-points (conversion shortcuts) are a little different: use instead

-
```
jupyter nbconvert --to html_lenvs FILE.ipynb
```
-
```
jupyter nbconvert --to html_toclenvs FILE.ipynb
```

## Conversion to LaTeX

We provide two templates `thmsInNb_article.tplx` and `thmsInNb_report.tplx` for article and report styles respectively. Anyway one can also use the standard article, report, book templates provided with nbconvert. Simply, we have improved some of the internals styles. More importantly, we provide an exporter class `LenvsLatexExporter` (also in library `latex_envs.py`). Using that class, conversion simply amounts to
```
jupyter nbconvert --to latex_envs.LenvsLatexExporter FILE.ipynb
```
A shortcut is also provided
```
jupyter nbconvert --to latex_with_lenvs FILE.ipynb
```
In addition, we provide several further options:

-  **removeHeaders**: Remove headers and footers, (default false)
-  **figcaptionProcess**: Process figcaptions, (default true)
- **tocrefRemove** Remove tocs and ref sections, + some cleaning, (default true),

These options can be specified on the command line as, eg,
```
jupyter nbconvert --to latex_with_lenvs --LenvsLatexExporter.removeHeaders=True -- LenvsLatexExporter.tocrefRemove=False FILE.ipynb
```

**If you use the version included in the jupyter_notebook_extensions collection**, the entry-points (conversion shortcuts) are a little different: use instead
```
jupyter nbconvert --to latex_lenvs FILE.ipynb
```

\begin{example}
As for an example, the present document has been converted using
```
jupyter nbconvert --to latex_with_lenvs --LenvsLatexExporter.removeHeaders=True latex_env_doc.ipynb
```

Then the resulting file (without header/footer) has been included in the main file `documentation.tex`, where some LaTeX definitions of environments are done (namely listings, colors, etc) and compiled using

- `xelatex -interaction=nonstopmode documentation`
- `bibTeX documentation`
- `xelatex -interaction=nonstopmode documentation`

The output can be consulted [here](documentation.pdf).
\end{example}

# Installation

The extension consists in a package that includes a javascript notebook extension. Since Jupyter 4.2, this is the recommended way to distribute nbextensions. The extension can be installed

- from the master version on the github repo (this will be always the most recent version)
- via pip for the version hosted on Pypi
- as part of the great [Jupyter-notebook-extensions](https://github.com/ipython-contrib/Jupyter-notebook-extensions) collection. Follow the instructions there for installing. Once this is done, you can open a tab at  `http://localhost:8888/nbextensions` to enable and configure the various extensions.

From the github repo or from Pypi,

- **step 1**: install the package
     - `pip3 install https://github.com/jfbercher/jupyter_latex_envs/archive/master.zip [--user][--upgrade]`
     -  <span style="color:blue"> or</span> `pip3 install jupyter_latex_envs [--user][--upgrade]`
     - <span style="color:blue"> or</span> clone the repo and install
   ```
   git clone https://github.com/jfbercher/jupyter_latex_envs.git
   python3 setup.py install
   ```

With Jupyter >= 4.2,

- **step 2**: install the notebook extension
```
jupyter nbextension install --py latex_envs [--user]
```

-  **step 3**: and enable it
```
jupyter nbextension enable latex_envs [--user] --py
```

For Jupyter versions before 4.2, the situation is more tricky since you will have to find the location of the source files (instructions from @jcb91 found [here](https://github.com/jcb91/jupyter_highlight_selected_word)): execute
```
python -c "import os.path as p; from jupyter_highlight_selected_word import __file__ as f, _jupyter_nbextension_paths as n; print(p.normpath(p.join(p.dirname(f), n()[0]['src'])))"
```
Then, issue
```
jupyter nbextension install <output source directory>
jupyter nbextension enable latex_envs/latex_envs
```
where `<output source directory>` is the output of the python command.

# Customization

## Configuration parameters

Some configuration parameters can be specified system-wide, using the `nbextension_configurator`. For that, open a browser at [http://localhost:8888/nbextensions/](http://localhost:8888/nbextensions/) -- the exact address may change eg if you use jupyterhub or if you use a non standard port. You will then be able to change default values for the boolean values
- LaTeX_envs menu (insert environments) present
- Label equation with numbers (otherwise with their \label{} key)
- Number environments as section.num
- Use customized environments as given in 'user_envs.json' (in the extension directory)
and enter a default filename for the bibtex file (in document directory).

All these values can also be changed per documents and these values are stored in the notebook's metadata.

## User environments configuration

Environments can be customized in the file `user_envs.json`, located in the `nbextensions/latex_envs` directory. It is even possible to add *new* environments. This file is read at startup (or when using the corresponding toggle option in the `Toggles` menu) and merged with the standard configuration. An example is provided as `example_user_envs.json`. For each (new/modified) environment, one has to  provide (i) the name of the environment (ii) its title (iii) the name of the associated counter for numbering it; eg
```
    "myenv": {
        "title": "MyEnv",
        "counterName": "example"
    },
```
Available counters are problem, exercise, example, property, theorem, lemma, corollary, proposition, definition, remark, and figure.

## Styling
The document title and the document author (as specified by `\title` and `\author` are formatted using the `maketitle` command according to the `.latex_maintitle` and `.latex_author` div styles.

Each environment is formatted according to the div style `.latex_environmentName`, e.g. `.latex_theorem`, `.latex_example`, etc. The titles of environments are formatted with respect to `.latex_title` and the optional parameter wrt `.latex_title_opt`.
Images are displayed using the style specified by `.latex_img` and thir caption using `.caption`.
Finally, enumerate environments are formatted according to the `.enum` style. Similarly, itemize environments are formatted using `.item` style.

These styles can be customized either in the `latex_envs.css` file, or better in a `custom.css` in the document directory.

# Usage and further examples

## First example (continued)

We continue the first example on fthe Fourier transform definition \ref{def:FT} in order to show that, of course, we can illustrate things using a simple code. Since the Fourier transform is an essential tool in signal processing, We put this in evidence using the `textboxa` environment -- which is defined here in the css, and that one should define in the LaTeX counterpart:
\begin{listing}
\begin{textboxa}
The Fourier transform is an extremely useful tool to have in your toolbox!
\end{textboxa}
\end{listing}

\begin{textboxa}
The Fourier transform is an extremely useful tool to have in your toolbox!
\end{textboxa}

The Fourier transform of a pure cosine is given by
$$
X[k] = \frac{1}{2} \left( \delta[k-k_0] + \delta[k-k_0] \right),
$$
modulo $N$. This is illustrated in the following simple script:

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from numpy.fft import fft
k0=4; N=128; n=np.arange(N); k=np.arange(N)
x=np.sin(2*np.pi*k0*n/N)
X=fft(x)
plt.stem(k,np.abs(X))
plt.xlim([0, 20])
plt.title("Fourier transform of a cosine")
_=plt.xlabel("Frequency index (k)")
```

## Second example

This example shows a series of environments, with different facets; **links, references, markdown or/and LaTeX formatting within environments**.  The listing of environments below is typed using the environment *listing*...

\begin{listing}
\begin{definition} \label{def:diffeq}
We call \textbf{difference equation} an equation of the form
$$
\label{eq:diffeq}
y[n]= \sum_{k=1}^{p} a_k y[n-k] + \sum_{i=0}^q b_i x[n-i]
$$
\end{definition}

\begin{property}
If all the $a_k$ in equation (\ref{eq:diffeq}) of definition \ref{def:diffeq} are zero, then the filter has a **finite impulse response**.
\end{property}

\begin{proof}
Let $\delta[n]$ denote the Dirac impulse. Take $x[n]=\delta[n]$ in (\ref{eq:diffeq}). This yields, by definition, the impulse response:
$$
\label{eq:fir}
h[n]= \sum_{i=0}^q b_i \delta[n-i],
$$
which has finite support.
\end{proof}

\begin{theorem}
The poles of a causal stable filter are located within the unit circle in the complex plane.
\end{theorem}

\begin{example} \label{ex:IIR1}
Consider $y[n]= a y[n-1] +  x[n]$. The pole of the transfer function is $z=a$. The impulse response $h[n]=a^n$ has infinite support.
\end{example}

In the following exercise, you will check that the filter is stable iff $a$<1.

\begin{exercise}\label{ex:exofilter}
Consider the filter defined in Example \ref{ex:IIR1}. Using the **function** `lfilter` of scipy, compute and plot the impulse response for several values of $a$.
\end{exercise}

\end{listing}

The lines above are rendered as follows (of course everything can be tailored in the stylesheet):
%
\begin{definition} \label{def:diffeq}
We call \textbf{difference equation} an equation of the form
\begin{equation}
\label{eq:diffeq}
y[n]= \sum_{k=1}^{p} a_k y[n-k] + \sum_{i=0}^q b_i x[n-i]
\end{equation}
\end{definition}
%
Properties of the filter are linked to the coefficients of the difference equation. For instance, an immediate property is
%
% this is a comment
\begin{property}
If all the $a_k$ in equation (\ref{eq:diffeq}) of definition \ref{def:diffeq} are zero, then the filter has a **finite impulse response**.
\end{property}
%
\begin{proof}
Let $\delta[n]$ denote the Dirac impulse. Take $x[n]=\delta[n]$ in (\ref{eq:diffeq}). This yields, by definition, the impulse response:
\begin{equation}
\label{eq:fir}
h[n]= \sum_{i=0}^q b_i \delta[n-i],
\end{equation}
which has finite support.
\end{proof}
%
\begin{theorem}
The poles of a causal stable filter are located within the unit circle in the complex plane.
\end{theorem}
%
\begin{example} \label{ex:IIR1}
Consider $y[n]= a y[n-1] +  x[n]$. The pole of the transfer function is $z=a$. The impulse response $h[n]=a^n$ has infinite support.
\end{example}

In the following exercise, you will check that the filter is stable iff $a$<1.
%
\begin{exercise}\label{ex:exofilter}
Consider the filter defined in Example \ref{ex:IIR1}. Using the **function** `lfilter` of scipy, compute and plot the impulse response for several values of $a$.
\end{exercise}

\begin{listing}
The solution of exercise \ref{ex:exofilter}, which uses a difference equation as in Definition \ref{def:diffeq}:
\end{listing}
The solution of exercise \ref{ex:exofilter}, which uses a difference equation as in Definition \ref{def:diffeq}:

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import lfilter
d=np.zeros(100); d[0]=1 #dirac impulse
alist=[0.2, 0.8, 0.9, 0.95, 0.99, 0.999, 1.001, 1.01]
for a in alist:
    h=lfilter([1], [1, -a],d)
    _=plt.plot(h, label="a={}".format(a))
plt.ylim([0,1.5])
plt.xlabel('Time')
_=plt.legend()
```

## Third example:

This example shows that environments like itemize or enumerate are also available. As already indicated, this is useful for copying text from a TeX file. Following the same idea, text formating commands `\textit`, `\textbf`, `\underline`, etc are also available.

\begin{listing}
The following \textit{environments} are available:
\begin{itemize}
    \item \textbf{Theorems and likes}
    \begin{enumerate}
        \item theorem,
        \item lemma,
        \item corollary
        \item ...
    \end{enumerate}
    \item \textbf{exercises}
    \begin{enumerate}
        \item problem,
        \item example,
        \item exercise
    \end{enumerate}
\end{itemize}
\end{listing}

which gives...

The following \textit{environments} are available:
\begin{itemize}
\item \textbf{Theorems and likes}
\begin{enumerate}
\item theorem,
\item lemma,
\item corollary
\item ...
\end{enumerate}
\item \textbf{exercises}
\begin{enumerate}
\item problem,
\item example,
\item exercise
\end{enumerate}
\end{itemize}

# Disclaimer, sources and thanks

Originally, I used a piece of code from the nice online markdown editor `stackedit` [https://github.com/benweet/stackedit/issues/187](https://github.com/benweet/stackedit/issues/187), where the authors also considered the problem of incorporating LaTeX markup in their markdown.

I also studied and used examples and code from [https://github.com/ipython-contrib/IPython-notebook-extensions](https://github.com/ipython-contrib/IPython-notebook-extensions).

- This is done in the hope it can be useful. However there are many impovements possible, in the code and in the documentation.
**Contributions will be welcome and deeply appreciated.**

- If you have issues, please post an issue at
`https://github.com/jfbercher/jupyter_latex_envs/issues` [here](https://github.com/jfbercher/jupyter_latex_envs/issues).

**Self-Promotion --** Like `latex_envs`? Please star and follow the [repository](https://github.com/jfbercher/jupyter_latex_envs) on GitHub.

# References

(<a id="cit-PER-GRA:2007" href="#call-PER-GRA:2007">P\'erez and Granger, 2007</a>) P\'erez Fernando and Granger Brian E., ``_IPython: a System for Interactive Scientific Computing_'', Computing in Science and Engineering, vol. 9, number 3, pp. 21--29, May 2007.  [online](http://ipython.org)

(<a id="cit-mckinney2012python" href="#call-mckinney2012python">McKinney, 2012</a>) Wes McKinney, ``_Python for data analysis: Data wrangling with Pandas, NumPy, and IPython_'',  2012.

(<a id="cit-rossant2013learning" href="#call-rossant2013learning">Rossant, 2013</a>) Cyrille Rossant, ``_Learning IPython for interactive computing and data visualization_'',  2013.

(<a id="cit-shen2014interactive" href="#call-shen2014interactive">Shen, 2014</a>) Shen Helen, ``_Interactive notebooks: Sharing the code_'', Nature, vol. 515, number 7525, pp. 151--152,  2014.

```python
%%html
<style>
    .prompt{
        display: none;
    }

</style>
```

<style>
    .prompt{
        display: none;
    }

</style>


# Monte Carlo Methods: Lab 2

```python
from IPython.core.display import HTML
css_file = 'https://raw.githubusercontent.com/ngcm/training-public/master/ipython_notebook_styles/ngcmstyle.css'
HTML(url=css_file)
```

<link href='http://fonts.googleapis.com/css?family=Open+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Nixie+One' rel='stylesheet' type='text/css'>
<style>

@font-face {
    font-family: "Computer Modern";
    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');
}

#notebook_panel { /* main background */
    background: rgb(245,245,245);
}

div.cell { /* set cell width */
    width: 1000px;
}

div #notebook { /* centre the content */
    background: #fff; /* white background for content */
    width: 1200px;
    margin: auto;
    padding-left: 0em;
}

#notebook li { /* More space between bullet points */
margin-top:0.8em;
}

/* draw border around running cells */
div.cell.border-box-sizing.code_cell.running {
    border: 1px solid #111;
}

/* Put a solid color box around each cell and its output, visually linking them*/
div.cell.code_cell {
    background-color: rgb(256,256,256);
    border-radius: 0px;
    padding: 0.5em;
    margin-left:1em;
    margin-top: 1em;
}

div.text_cell_render{
    font-family: 'Open Sans' sans-serif;
    line-height: 140%;
    font-size: 125%;
    font-weight: 400;
    width:900px;
    margin-left:auto;
    margin-right:auto;
}

/* Formatting for header cells */
.text_cell_render h1 {
    font-family: 'Arvo', serif;
    font-style:regular;
    font-weight: 400;
    font-size: 45pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.5em;
    margin-top: 0.5em;
    display: block;
}
.text_cell_render h2 {
    font-family: 'Arvo', serif;
    font-weight: 400;
    font-size: 30pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    display: block;
}

.text_cell_render h3 {
    font-family: 'Arvo', serif;
    margin-top:16px;
	font-size: 22pt;
    font-weight: 600;
    margin-bottom: 3px;
    font-style: regular;
    color: rgb(102,102,0);
}

.text_cell_render h4 {    /*Use this for captions*/
    font-family: 'Arvo', serif;
    font-size: 14pt;
    text-align: center;
    margin-top: 0em;
    margin-bottom: 2em;
    font-style: regular;
}

.text_cell_render h5 {  /*Use this for small titles*/
    font-family: 'Arvo', sans-serif;
    font-weight: 400;
    font-size: 16pt;
    color: rgb(163,0,0);
    font-style: italic;
    margin-bottom: .1em;
    margin-top: 0.8em;
    display: block;
}

.text_cell_render h6 { /*use this for copyright note*/
    font-family: 'PT Mono', sans-serif;
    font-weight: 300;
    font-size: 9pt;
    line-height: 100%;
    color: grey;
    margin-bottom: 1px;
    margin-top: 1px;
}

.CodeMirror{
        font-family: "PT Mono";
        font-size: 90%;
}

</style>

## Previous Lab

The key point of the previous lab was that if you can draw random samples from a suitable distribution you can calculate some quantity using the "average" value of some function of the distribution.

The modelling issue boils down to: how do we construct the samples or the distribution? If you know the distribution you can use rejection sampling as in lab 1. If you don't know the distribution, you can still compute the samples indirectly using Monte Carlo methods. In particular, let's look at Monte Carlo Markov Chain (MCMC) methods and the Metropolis-Hastings algorithm.

## Ideal gas

Let's put $N$ particles of mass $1$ inside a cubic box, each side having length $1$. Each particle is described by three quantum numbers $n_x, n_y, n_z = 1, \dots, \infty$, which are positive integers. The energy of each particle is

$$
  E^{(i)} \left( n_x^{(i)}, n_y^{(i)}, n_z^{(i)} \right)  = \frac{h^2}{8 \pi} \left( \left( n_x^{(i)} \right)^2 + \left( n_y^{(i)} \right)^2 + \left( n_z^{(i)} \right)^2 \right).
$$

In an ideal gas there is no interaction between the particles, so the total energy is

$$
  E = \sum_{i=1}^N E^{(i)} \left( n_x^{(i)}, n_y^{(i)}, n_z^{(i)} \right).
$$

Now, we can easily compute the energy of any given set of particles (we'll use units where $h=2 \pi$):

```python

```

We could now draw lots of samples of the quantum numbers and find the most likely energy, which we expect to be the ground state. However, this would be ludicrously expensive. We want the equivalent of importance sampling: finding the "right" samples to do the measurement in the first place.

## Markov Chains

The trick here is to think about *linking* different sets of random samples. Each set of $N$ particles is a single draw from a random distribution. What we want to do is *not* to jump from one draw to the next at random, but to say *how likely* it is that we would go from one draw to another. If this probability depends only on where we are, not where we've been, then we have a *Markov Chain*. If this process of transitioning from one draw to the next obeys

1. detailed balance - the probability of moving from state $i$ to state $j$ is the same as the probability of moving from state $j$ to state $i$, and
2. ergodicity - every state can be reached by some transition,

then the Markov Chain will settle down, or *equilibriate*, to the most likely state.

So we need to choose a method of moving from one draw - one set of particles - to the next, using only the information that we have: the energy. There are many ways of doing this.

### Metropolis-Hastings

The Metropolis-Hastings algorithm starts from the assumption that the ground state will try to minimize its energy. Therefore the samples $n_j$ with energy $E_j$ is "better" than the samples $n_i$ with energy $E_i$ if $E_j < E_i$.

However, the rule to only accept a transition from samples with high energy to samples with low energy doesn't match detailed balance. There must be *some* chance of moving to a state with higher energy. This probability must match the qualitative form of the overall distribution. If we make the assumption that the energies follow the Boltzmann distribution, then the chance of a state appearing with $E_j > E_i$ is $\sim \exp \left[-\beta \left( E_j - E_i \right) \right]$, where $\beta$ is $k_B T$ ($k_B$ is the Boltzmann constant and $T$ the temperature of the system).

So, the Metropolis-Hastings algorithm is:

1. Draw some sample $n_0$ with energy $E_0$. Set $i=0$.
2. Draw a random sample $n_{j}$ with energy $E_j$.
3. If $E_j < E_i$ accept the new sample, set $i=j$.
4. If $E_j > E_i$, accept the new sample with probability $P_a = \exp \left[-\beta \left( E_j - E_i \right) \right]$. That is, compute a uniform random number $U$ and accept the new sample if $U < P_a$.
5. Repeat from 2 until the system equilibriates.

Now, our new sample $n_j$ could change the quantum states of *all* the particles, or just *one* particle, or just one quantum state of one particle. It's usual (but not necessary) to start with making the smallest change, so let's start by changing a single quantum state and either flip it up with probability $1/2$ or down with probability $1/2$.

Let's look at that case with $\beta = 0.1$.

```python

```

```python

```

## Parameter study

If we want to model the gas macroscopically we will average over the particles to get an equation of state. The result would be the functional form of the energy $E$ as a function of the density $\rho = N/V$, holding other variables fixed. Use the MCMC code to get $E(\rho)$ for $\rho \in [10^1, 10^4]$ (which indirectly varies $N$), with other parameters as above.

```python

```

## Lennard-Jones fluids

Point to note: an electronic copy of the [Frenkel and Smit book is available through the library](http://site.ebrary.com/lib/soton/detail.action?docID=10186686). This lab is based on case study 1 in chapter 3.4 of that book.

When computing the interactions between lots of bodies (atoms, molecules, planets, etc) we can either use the *true* potential or force between them, or we can approximate it with some potential (or force) that is easier (and usually cheaper) to calculate. The parameters of the potential can then be set to approximate the "real" features we're interested in.

In computational chemistry, one such approximation is the *Lennard-Jones* potential. Given two bodies separated by a distance $r$, the potential generated by those two bodies is

\begin{equation}
  U(r) = 4 \varepsilon \left[ \left( \frac{\sigma}{r} \right)^{12} - \left( \frac{\sigma}{r} \right)^{6} \right].
\end{equation}

Here $\varepsilon$ and $\sigma$ are parameters. When there are more than two bodies the total potential is the sum over all pairwise potentials.

In principle this generates a potential between particles that are separated by huge distances. Instead it is typical to *truncate* the potential: to pick a cut-off distance so that any particles separated by more than that distance do not contribute, and to correct for those small contributions.

Here we use a Lennard-Jones potential inside a box size $[0,L]^3$ with a cut-off $r_c = L/2$, with parameters set so that

\begin{equation}
U = \begin{cases} 4 \left[ \frac{1}{r^{12}} - \frac{1}{r^6} \right] & r < r_c \\ 0 & r > r_c. \end{cases}
\end{equation}

Include tail corrections (that is, additional energy and pressure terms resulting from the particles outside the cutoff radius) as

\begin{align}
  U^{\text{tail}} & = \frac{8 \pi \rho}{3} \left[ \frac{1}{3} \frac{1}{r_c^9} - \frac{1}{r_c^3} \right] \\
  p^{\text{tail}} & = \frac{16 \pi \rho^2}{3} \left[ \frac{2}{3} \frac{1}{r_c^9} - \frac{1}{r_c^3} \right].
\end{align}

For each configuration we need to compute the pressure using

$$
\begin{equation}
  p = \frac{\rho}{\beta} + \frac{\text{Virial}}{V}
\end{equation}
$$

where

$$
\begin{equation}
  \text{Virial} = \sum_i \sum_{j > i} \vec{f}( \vec{r}_{ij} ) \cdot \vec{r}_{ij}
\end{equation}
$$

where, as usual, $\vec{r}_{ij}$ is the separation between the atoms, $\vec{r}_{ij} = \vec{r}_i - \vec{r}_j$, and the intermolecular force $\vec{f}$ is given by

$$
\begin{align}
  \vec{f}(\vec{r}_{ij}) &= - \nabla U \\
  & = \begin{cases} 24 \left[ 2 \frac{1}{r^{14}} - \frac{1}{r^8} \right] \vec{r}_{ij} & r < r_c \\ \vec{0} & r > r_c \end{cases}
\end{align}
$$

Note that in the reduced coordinates $\beta = T^{-1}$.

## Monte Carlo code

We will be using an $NTV$ approach, keeping the number of particles fixed ($N = 100$), the temperature fixed ($T=2$) and the volume fixed (indirectly, via the density $\rho = N / V = N L^{-3}$; use $\rho = a/10$ for $a = 1, \dots, 9$, but start by just considering the $a=1, 2$ cases). You will need to take at least $10,000$ steps for the larger values of $a$; $20,000$ is better, but in all cases you should test with a smaller number of particles and steps ($1,000$ may be sufficient for small values of $a$).

For reference we note the solutions, taken from [Johnson, Zollweg and Gubbins](http://www.tandfonline.com/doi/abs/10.1080/00268979300100411) for the pressures at $T=2$ are:

```python
p_JZG_T2 = [0.1776, 0.329, 0.489, 0.7, 1.071, 1.75, 3.028, 5.285, 9.12]
```

### Efficiency

Note that the sum over all particles scales as $n^2$ where $n$ is the number of particles. As the number of steps the algorithm will need to take will also scale as $n$, this makes the number of calculations at least as bad as $n^3$. This is expensive; if you try the naive approach then you'll have difficulty using more than 50 particles in a moderate time.

Instead we can note that, at each stage, the algorithm will move only one particle. Therefore, if we store not just the locations of the particles but also their pairwise separations, at each step we will only have to modify a small number of the separations. So we can store $r^2_{ij} = \vec{r}_{ij} \cdot \vec{r}_{ij}$ only, for $j > i$, and when perturbing particle $k$ we only need to update the separations $r^2_{ik}$ for $i<k$ and $r^2_{kj}$ for $k<j$.

This should significantly reduce the number of calculations done in each step.

In addition, note that for reasonable behaviour the acceptance rate should be $\sim 40\%$. This depends on the fractional perturbation distance $\Delta$; values $\sim 0.4$ are reasonable when $\rho \sim 0.1$, but values $\sim 0.02$ are reasonable when $\rho \sim 0.9$.

### Results

* Check that the energy has converged to a "constant" state.
* Plot a histogram of the energies to show that they follow the Boltzmann distribution.

```python
%matplotlib inline
import numpy
from scipy import constants
from matplotlib import pyplot
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 16
rcParams['figure.figsize'] = (12,6)
```

FEEG6016 Simulation and Modelling/02-Monte-Carlo-Lab-2.ipynb


# Advanced: Extending lambeq

## Creating readers

### [Reader](../lambeq.rst#lambeq.reader.Reader) example: "Comb" reader

In this example we will create a reader that, given a sentence, it generates the following tensor network:

<center>

</center>

Note that the particular compositional model is not appropriate for classical experiments, since the tensor that implements the layer can become very large for long sentences. However, the model can be implemented without problems on a quantum computer.

```python
from lambeq.reader import Reader
from lambeq.core.types import AtomicType
from discopy import Box, Id, Word

N = AtomicType.NOUN

class CombReader(Reader):
    def sentence2diagram(self, sentence):
        words = Id().tensor(*[Word(w, N) for w in sentence.split()])
        layer = Box('LAYER', words.cod, N)
        return words >> layer

diagram = CombReader().sentence2diagram('John gave Mary a flower')
diagram.draw()
```

```python
Id().tensor(*[Word(w, N) for w in ['John', 'gave', 'Mary', 'a', 'flower']]).draw()
```

## Creating rewrite rules

```python
import warnings
warnings.filterwarnings('ignore')  # Ignore warnings

from lambeq.ccg2discocat import DepCCGParser

parser = DepCCGParser()
d = parser.sentence2diagram('The food is fresh')
```

### [SimpleRewriteRule](../lambeq.rst#lambeq.rewrite.SimpleRewriteRule) example: Negation functor

```python
from lambeq.rewrite import SimpleRewriteRule
from lambeq.core.types import AtomicType
from discopy.rigid import Box, Id

N = AtomicType.NOUN
S = AtomicType.SENTENCE
adj = N @ N.l

NOT = Box('NOT', S, S)

negation_rewrite = SimpleRewriteRule(
    cod=N.r @ S @ S.l @ N,
    template=SimpleRewriteRule.placeholder(N.r @ S @ S.l @ N) >> Id(N.r) @ NOT @ Id(S.l @ N),
    words=['is', 'was', 'has', 'have'])
```

```python
from lambeq.rewrite import Rewriter
from discopy import drawing

not_d = Rewriter([negation_rewrite])(d)
drawing.equation(d, not_d, symbol='->', figsize=(14, 4))
```

### [RewriteRule](../lambeq.rst#lambeq.rewrite.RewriteRule) example: "Past" functor

```python
from lambeq.rewrite import RewriteRule

class PastRewriteRule(RewriteRule):
    mapping = {
        'is': 'was',
        'are': 'were',
        'has': 'had'
    }
    def matches(self, box):
        return box.name in self.mapping

    def rewrite(self, box):
        new_name = self.mapping[box.name]
        return type(box)(name=new_name, dom=box.dom, cod=box.cod)
```

```python
past_d = Rewriter([PastRewriteRule()])(d)
drawing.equation(d, past_d, symbol='->', figsize=(14, 4))
```

## Creating ansätze

```python
d = parser.sentence2diagram('We will go')
```

### [CircuitAnsatz](../lambeq.rst#lambeq.circuit.CircuitAnsatz) example: "Real-valued" ansatz

```python
from lambeq.circuit import CircuitAnsatz
from discopy.quantum.circuit import Functor, Id
from discopy.quantum.gates import Bra, CX, Ket, Ry
from lambeq.ansatz import Symbol

class RealAnsatz(CircuitAnsatz):
    def __init__(self, ob_map, n_layers):
        super().__init__(ob_map=ob_map, n_layers=n_layers)

        self.n_layers = n_layers
        self.functor = Functor(ob=self.ob_map, ar=self._ar)

    def _ar(self, box):
        # step 1: obtain label
        label = self._summarise_box(box)

        # step 2: map domain and codomain
        dom, cod = self._ob(box.dom), self._ob(box.cod)

        n_qubits = max(dom, cod)
        n_layers = self.n_layers

        # step 3: construct and return ansatz
        if n_qubits == 1:
            circuit = Ry(Symbol(f'{label}_0'))
        else:
            # this also deals with the n_qubits == 0 case correctly
            circuit = Id(n_qubits)
            for i in range(n_layers):
                offset = i * n_qubits
                syms = [Symbol(f'{label}_{offset + j}') for j in range(n_qubits)]

                # adds a ladder of CNOTs
                for j in range(n_qubits - 1):
                    circuit >>= Id(j) @ CX @ Id(n_qubits - j - 2)

                # adds a layer of Y rotations
                circuit >>= Id().tensor(*[Ry(sym) for sym in syms])

        if cod <= dom:
            circuit >>= Id(cod) @ Bra(*[0]*(dom - cod))
        else:
            circuit <<= Id(dom) @ Ket(*[0]*(cod - dom))
        return circuit
```

```python
real_d = RealAnsatz({N: 1, S: 1}, n_layers=2)(d)
real_d.draw(figsize=(12, 10))
```

### [TensorAnsatz](../lambeq.rst#lambeq.tensor.TensorAnsatz) example: "Positive" ansatz

```python
from lambeq.tensor import TensorAnsatz
from discopy import rigid, tensor
from functools import reduce

class PositiveAnsatz(TensorAnsatz):
    def _ar(self, box):
        # step 1: obtain label
        label = self._summarise_box(box)

        # step 2: map domain and codomain
        dom, cod = self._ob(box.dom), self._ob(box.cod)

        # step 3: construct and return ansatz
        name = self._summarise_box(box)
        n_params = reduce(lambda x, y: x * y, dom @ cod, 1)
        syms = Symbol(name, size=n_params)
        return tensor.Box(box.name, dom, cod, syms ** 2)
```

```python
from discopy import Dim

ansatz = PositiveAnsatz({N: Dim(2), S: Dim(2)})
positive_d = ansatz(d)
positive_d.draw()
```

```python
import numpy as np
from sympy import default_sort_key

syms = sorted(positive_d.free_symbols, key=default_sort_key)
sym_dict = {k: -np.ones(k.size) for k in syms}
subbed_diagram = positive_d.lambdify(*syms)(*sym_dict.values())

subbed_diagram.eval()
```

    Tensor(dom=Dim(1), cod=Dim(2), array=[8., 8.])

## Contributions