Commit 82fadcff authored by Anton Akhmerov's avatar Anton Akhmerov
Browse files

Merge branch 'jupyter-book' into 'master'

Switch to jupyter-book for rendering

See merge request !55
parents ddb03105 deaf64d3
Pipeline #81682 passed with stages
in 4 minutes and 14 seconds
*
!environment.yml
\ No newline at end of file
*.ipynb filter=nb-filters
......@@ -20,13 +20,10 @@ auto
# Python auxiliary files
*.pyc
.ropeproject
# Cached output
.nb_output_cache
.vscode
# Misc
.DS_Store
# Output files
generated
_build
image: topocourse/topocourse
image: topocourse/topocourse:book
stages:
- execute
- build
- deploy
execute_ipynbs:
stage: execute
before_script:
- pip install ruamel.yaml git+https://gitlab.kwant-project.org/anton-akhmerov/publist.git
stage: build
script:
- export PYTHONPATH=$PYTHONPATH:${PWD}/code
- export OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 MKL_DYNAMIC=FALSE
- export MARKDOWN=generated/markdown
- mkdir -p $MARKDOWN
- cp -r src/* $MARKDOWN
- python scripts/preprocess_markdown.py
- export WITH_OUTPUT=generated/with_output
- cp -r data $WITH_OUTPUT
- cp -r $MARKDOWN/* $WITH_OUTPUT
- find $WITH_OUTPUT -name '*.md' | parallel --delay 3 --jobs 32 notedown -o --run --timeout -1 --match fenced
- rm -rf $WITH_OUTPUT/data
- jupyter-book build .
# Workaround of https://github.com/executablebooks/MyST-NB/issues/287
- cp _static/mystnb.css _build/html/_static/
artifacts:
paths:
- generated/with_output
- _build/html
expire_in: 7d
cache:
- key: global
paths:
- _build/
mirror to github:
stage: execute
stage: build
allow_failure: true
only:
- branches@qt/topocm
......@@ -47,55 +40,13 @@ mirror to github:
- for REPO in $REPOS; do git push --mirror $REPO; done
edx archive:
stage: build
before_script:
- pip install ruamel.yaml
script: ./scripts/converter.py ./generated/with_output
artifacts:
paths:
- generated/import_to_edx.tar.gz
- generated/html/edx
expire_in: 7d
pelican website:
stage: build
variables:
DEST: "generated/html"
before_script:
- pip install ruamel.yaml
script:
- python scripts/converter_pelican.py
- pelican -o $DEST/ -s website_assets/pelicanconf.py generated/pelican_content
artifacts:
paths:
- generated/html
expire_in: 30d
ocw website:
stage: build
before_script:
- pip install ruamel.yaml
script:
- python scripts/converter_ocw.py
- mv website_assets/iframes.txt generated/html/ocw
artifacts:
paths:
- generated/html/ocw
expire_in: 1d
.upload_website: &upload_website
stage: deploy
before_script:
- mkdir -p ~/.ssh && ssh-keyscan tnw-tn1.tudelft.net >> ~/.ssh/known_hosts
- echo $WEBSITE_KEY | base64 -d > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
script:
- cp -r generated/with_output generated/html/notebooks
- "rsync -ravz --delete generated/html/* $USER@tnw-tn1.tudelft.net:"
- "rsync -ravz --delete website_assets/static $USER@tnw-tn1.tudelft.net:"
- "rsync -ravz _build/html/* $USER@tnw-tn1.tudelft.net:"
after_script:
- rm -rf ~/.ssh
......
......@@ -48,11 +48,18 @@ ENV LANGUAGE en_US.UTF-8
RUN cd /tmp && \
mkdir -p $CONDA_DIR && \
wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.2-Linux-x86_64.sh && \
/bin/bash Miniconda3-py37_4.8.2-Linux-x86_64.sh -f -b -p $CONDA_DIR && \
rm Miniconda3-py37_4.8.2-Linux-x86_64.sh
wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-py39_4.10.3-Linux-x86_64.sh && \
/bin/bash Miniconda3-py39_4.10.3-Linux-x86_64.sh -f -b -p $CONDA_DIR && \
rm Miniconda3-py39_4.10.3-Linux-x86_64.sh && \
conda install mamba -n base -c conda-forge
# Add environment file
COPY python3.yaml .
COPY environment.yml .
RUN conda env update -n root -f python3.yaml && conda clean -tipsy
RUN mamba env update -n base -f environment.yml && mamba clean --all
# setting openblas and mkl variables
ENV OPENBLAS_NUM_THREADS=1\
OMP_NUM_THREADS=1\
MKL_DYNAMIC=FALSE\
MKL_NUM_THREADS=1
title: 'Topology in condensed matter: tying quantum knots'
author: Topology course team
copyright: "2021, TU Delft, CC-BY-SA 4.0 (materials) & BSD (code)"
exclude_patterns:
- _build
- src # Obsolete, should eventually be wiped
- "**.ipynb_checkpoints"
- readme.md
execute:
execute_notebooks: cache
timeout: -1
stderr_output: remove-warn
sphinx:
config:
html_js_files:
- https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js
- - https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js
- crossorigin: anonymous
- - https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js
- crossorigin: anonymous
- - https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js
- crossorigin: anonymous
- - https://unpkg.com/@holoviz/panel@0.10.2/dist/panel.min.js
- crossorigin: anonymous
local_extensions:
expand_refs: ./expand_refs/
launch_buttons:
binderhub_url: "" # Turn off binder for now
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setCookieDomain", "*.topocondmat.org"]);
_paq.push(["setDomains", ["*.topocondmat.org","*.test.topocondmat.org","*.www.topocondmat.org"]]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://piwik.kwant-project.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '4']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
/* Whole cell */
div.container.cell {
padding-left: 0;
margin-bottom: 1em;
}
/* Removing all background formatting so we can control at the div level */
.cell_input div.highlight, .cell_input pre, .cell_output pre,.cell_output .output {
border: none;
box-shadow: none;
}
.cell_output .output pre, .cell_input pre {
margin: 0px;
}
/* Input cells */
div.cell div.cell_input {
padding-left: 0em;
padding-right: 0em;
border: 1px #ccc solid;
background-color: #f7f7f7;
border-left-color: green;
border-left-width: medium;
}
div.cell_input > div, div.cell_output div.output > div.highlight {
margin: 0em !important;
border: none !important;
}
/* All cell outputs */
.cell_output {
padding-left: 1em;
padding-right: 0em;
margin-top: 1em;
}
/* Outputs from jupyter_sphinx overrides to remove extra CSS */
div.section div.jupyter_container {
padding: .4em;
margin: 0 0 .4em 0;
background-color: none;
border: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
/* Text outputs from cells */
.cell_output .output.text_plain,
.cell_output .output.traceback,
.cell_output .output.stream,
.cell_output .output.stderr
{
background: #fcfcfc;
margin-top: 1em;
margin-bottom: 0em;
box-shadow: none;
}
.cell_output .output.text_plain,
.cell_output .output.stream,
.cell_output .output.stderr {
border: 1px solid #f7f7f7;
}
.cell_output .output.stderr {
background: #fdd;
}
.cell_output .output.traceback {
border: 1px solid #ffd6d6;
}
/* Math align to the left */
.cell_output .MathJax_Display {
text-align: left !important;
}
/* Pandas tables. Pulled from the Jupyter / nbsphinx CSS */
div.cell_output table {
border: none;
border-collapse: collapse;
border-spacing: 0;
color: black;
font-size: 1em;
table-layout: fixed;
}
div.cell_output thead {
border-bottom: 1px solid black;
vertical-align: bottom;
}
div.cell_output tr,
div.cell_output th,
div.cell_output td {
text-align: right;
vertical-align: middle;
padding: 0.5em 0.5em;
line-height: normal;
white-space: normal;
max-width: none;
border: none;
}
div.cell_output th {
font-weight: bold;
}
div.cell_output tbody tr:nth-child(odd) {
background: #f5f5f5;
}
div.cell_output tbody tr:hover {
background: rgba(66, 165, 245, 0.2);
}
/* Inline text from `paste` operation */
span.pasted-text {
font-weight: bold;
}
span.pasted-inline img {
max-height: 2em;
}
tbody span.pasted-inline img {
max-height: none;
}
/* Font colors for translated ANSI escape sequences
Color values are adapted from share/jupyter/nbconvert/templates/classic/static/style.css
*/
div.highlight .-Color-Bold {
font-weight: bold;
}
div.highlight .-Color[class*=-Black] {
color :#3E424D
}
div.highlight .-Color[class*=-Red] {
color: #E75C58
}
div.highlight .-Color[class*=-Green] {
color: #00A250
}
div.highlight .-Color[class*=-Yellow] {
color: yellow
}
div.highlight .-Color[class*=-Blue] {
color: #208FFB
}
div.highlight .-Color[class*=-Magenta] {
color: #D160C4
}
div.highlight .-Color[class*=-Cyan] {
color: #60C6C8
}
div.highlight .-Color[class*=-White] {
color: #C5C1B4
}
div.highlight .-Color[class*=-BGBlack] {
background-color: #3E424D
}
div.highlight .-Color[class*=-BGRed] {
background-color: #E75C58
}
div.highlight .-Color[class*=-BGGreen] {
background-color: #00A250
}
div.highlight .-Color[class*=-BGYellow] {
background-color: yellow
}
div.highlight .-Color[class*=-BGBlue] {
background-color: #208FFB
}
div.highlight .-Color[class*=-BGMagenta] {
background-color: #D160C4
}
div.highlight .-Color[class*=-BGCyan] {
background-color: #60C6C8
}
div.highlight .-Color[class*=-BGWhite] {
background-color: #C5C1B4
}
format: jb-book
root: syllabus
parts:
- caption: Before you begin
chapters:
- file: w0_background/intro
- file: w0_background/band_structures
- caption: Topology in toy models
chapters:
- file: w1_topointro/0d
- file: w1_topointro/1D
- file: w1_topointro/w1_assignments
- caption: Majoranas I
chapters:
- file: w2_majorana/nanowire
- file: w2_majorana/signatures
- file: w2_majorana/braiding
- file: w2_majorana/w2_assignments
- caption: 'More parameters: charge pumping'
chapters:
- file: w3_pump_QHE/pumps
- file: w3_pump_QHE/Laughlinargument
- file: w3_pump_QHE/QHEedgestates
- file: w3_pump_QHE/w3_assignments
- caption: Chern insulators
chapters:
- file: w4_haldane/QHE_lattice
- file: w4_haldane/haldane_model
- file: w4_haldane/w4_assignments
- caption: Quantum spin Hall effect
chapters:
- file: w5_qshe/fermion_parity_pump
- file: w5_qshe/qshe_experiments
- file: w5_qshe/w5_assignments
- caption: Three-dimensional topological insulators
chapters:
- file: w6_3dti/bhz
- file: w6_3dti/3dti_signatures
- file: w6_3dti/w6_assignments
- caption: Topological defects
chapters:
- file: w7_defects/ti_majoranas
- file: w7_defects/crystalline_defects
- file: w7_defects/w7_assignments
- caption: General approach to topological classification
chapters:
- file: w8_general/classification
- file: w8_general/invariants
- file: w8_general/w8_assignments
- caption: Anderson localization and topology
chapters:
- file: w9_disorder/scaling
- file: w9_disorder/topoflow
- file: w9_disorder/w9_assignments
- caption: Extensions of classification I
chapters:
- file: w10_extensions/gapless
- file: w10_extensions/mechanics
- file: w10_extensions/w10_assignments
- caption: Extensions of classification II
chapters:
- file: w11_extensions2/floquet
- file: w11_extensions2/cti
- file: w11_extensions2/w11_assignments
- caption: Beyond single-particle physics
chapters:
- file: w12_manybody/fqhe
- file: w12_manybody/topoorder
- file: w12_manybody/w12_assignments
- caption: Appendices
chapters:
- file: w2_majorana/Peierls
- file: w4_haldane/ComputingChern
\ No newline at end of file
......@@ -10,16 +10,11 @@ from xml.etree.ElementTree import Element, SubElement
import feedparser
from IPython import display
module_dir = os.path.dirname(__file__)
sys.path.extend(module_dir)
__all__ = [
"MoocVideo",
"MoocDiscussion",
"MoocCheckboxesAssessment",
"MoocMultipleChoiceAssessment",
"MoocSelfAssessment",
"Video",
"Checkboxes",
"MultipleChoice",
]
......@@ -38,48 +33,11 @@ def _replace_latex_delimiters(text):
return re.sub(r"\$(.+?)\$", (lambda match: fr"\({match.group(1)}\)"), text)
class MoocComponent:
def _repr_mimebundle_(self, include, exclude):
return {
"application/vnd.edx.olxml+xml": ElementTree.tostring(
self.xml, encoding="unicode"
),
}
class MoocVideo(MoocComponent, display.YouTubeVideo):
class Video(display.YouTubeVideo):
def __init__(
self,
id,
src_location=None,
res="720",
display_name="",
download_track="true",
download_video="true",
show_captions="true",
**kwargs,
):
"""A video component of an EdX mooc embeddable in IPython notebook."""
self.xml = Element(
"video",
attrib=dict(
youtube=f"1.00:{id}",
youtube_id_1_0=id,
display_name=display_name,
download_track=download_track,
download_video=download_video,
show_captions=show_captions,
**kwargs,
),
)
if src_location is not None:
self.xml.attrib["source"] = (
"http://delftxdownloads.tudelft.nl/TOPOCMx-QuantumKnots/"
f"TOPOCMx-{src_location}-video.{res}.mp4"
)
super().__init__(id, rel=0, cc_load_policy=1)
def _repr_html_(self):
......@@ -89,43 +47,16 @@ class MoocVideo(MoocComponent, display.YouTubeVideo):
)
class MoocSelfAssessment(MoocComponent):
def __init__(self):
self.placeholder = (
"<p><b> MoocSelfAssessment description</b></p>\n"
"<p><b>In the live version of the course, you would "
"need to share your solution and grade yourself."
"</b></p>"
)
content_filename = module_dir + "/xmls/openassessment_self.xml"
with open(content_filename, "r") as content_file:
self.xml = xml = ElementTree.fromstring(content_file.read())
assessment = xml.find("assessments").find("assessment")
xml.attrib["submission_start"] = "2001-12-31T10:00:00Z"
xml.attrib["submission_due"] = "2100-12-31T10:00:00Z"
assessment.attrib["start"] = "2001-12-31T10:00:00Z"
assessment.attrib["due"] = "2100-12-31T10:00:00Z"
def _repr_html_(self):
return self.placeholder
class MoocCheckboxesAssessment(MoocComponent):
class Checkboxes:
def __init__(
self,
question,
answers,
correct_answers,
max_attempts=2,
display_name="Question",
explanation=None,
):
"""
MoocCheckboxesAssessment component
A checkboxes html component
input types
-----------
......@@ -135,29 +66,6 @@ class MoocCheckboxesAssessment(MoocComponent):
correct_answers : list of int
"""
self.xml = xml = Element(
"problem",
attrib=dict(display_name=display_name, max_attempts=str(max_attempts),),
)
sub = SubElement(xml, "choiceresponse")
SubElement(sub, "label").text = _replace_latex_delimiters(question)
SubElement(sub, "description").text = "Select the answers that match"
sub = SubElement(sub, "checkboxgroup")
sub.attrib["direction"] = "vertical"
for i, ans in enumerate(answers):
choice = SubElement(sub, "choice")
if i in correct_answers:
choice.attrib["correct"] = "true"
else:
choice.attrib["correct"] = "false"
choice.text = _replace_latex_delimiters(ans)
if explanation is not None:
_add_solution(xml, _replace_latex_delimiters(explanation))
self.question = question
self.answers = answers
self.correct_answers = correct_answers
......@@ -195,18 +103,16 @@ class MoocCheckboxesAssessment(MoocComponent):
return s.format(secrets.token_urlsafe(20), answer)
class MoocMultipleChoiceAssessment(MoocComponent):
class MultipleChoice:
def __init__(
self,
question,
answers,
correct_answer,
max_attempts=2,
display_name="Question",
explanation=None,
):
"""
MoocMultipleChoiceAssessment component
Multiple choice question html component
Parameters:
-----------
......@@ -216,29 +122,6 @@ class MoocMultipleChoiceAssessment(MoocComponent):
correct_answers : int
"""
self.xml = xml = Element(
"problem",
attrib=dict(display_name=display_name, max_attempts=str(max_attempts),),
)
sub = SubElement(xml, "multiplechoiceresponse")
SubElement(sub, "label").text = _replace_latex_delimiters(question)
SubElement(sub, "description").text = "Select the correct answer"
sub = SubElement(sub, "choicegroup")
sub.attrib["type"] = "MultipleChoice"
for i, ans in enumerate(answers):