├── .github └── workflows │ ├── cache.yml │ ├── ci.yml │ ├── coverage.yml │ ├── deploy-s3.yml │ └── preview.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── conf.py ├── environment.yml ├── requirements.txt ├── scripts ├── build-website.sh ├── execution-test.sh ├── linkchecker-test.sh └── travis-coverage.sh ├── sitemap.xml ├── source ├── _static │ ├── includes │ │ ├── header.raw │ │ └── lecture_howto_py.raw │ ├── lecture_specific │ │ ├── about_py │ │ │ ├── bn_density1.png │ │ │ ├── career_vf.png │ │ │ ├── pandas_vs_matlab.png │ │ │ ├── python_vs_matlab.png │ │ │ ├── qs.png │ │ │ └── qs.py │ │ ├── getting_started │ │ │ ├── editing_vim.png │ │ │ ├── ipython_shell.png │ │ │ ├── jp_demo.png │ │ │ ├── nb.png │ │ │ ├── nb2.png │ │ │ ├── nb3.png │ │ │ ├── nb6.png │ │ │ ├── nb6a.png │ │ │ ├── nb7.png │ │ │ ├── nb8.png │ │ │ ├── nb_run.png │ │ │ ├── nb_upload.png │ │ │ ├── nb_wntest2.png │ │ │ └── starting_nb.png │ │ ├── matplotlib │ │ │ └── matplotlib_ex1.png │ │ ├── pandas │ │ │ ├── data │ │ │ │ ├── test_pwt.csv │ │ │ │ └── ticker_data.csv │ │ │ ├── pandas_indices_pctchange.png │ │ │ ├── pandas_share_prices.png │ │ │ ├── pandas_vs_rest.png │ │ │ └── wb_download.py │ │ ├── parallelization │ │ │ └── htop_parallel_npmat.png │ │ ├── python_advanced_features │ │ │ ├── numbers.txt │ │ │ └── test_table.csv │ │ ├── python_by_example │ │ │ ├── pbe_ex2_fig.png │ │ │ └── test_program_1_updated.png │ │ ├── python_foundations │ │ │ ├── test_table.csv │ │ │ └── us_cities.txt │ │ ├── sci_libs │ │ │ └── nfs_ex1.png │ │ └── troubleshooting │ │ │ └── launch.png │ └── qe-logo-large.png └── rst │ ├── .ipynb_checkpoints │ ├── Untitled-checkpoint.ipynb │ └── changethis-checkpoint.ipynb │ ├── 404.rst │ ├── _static │ ├── about_lectures.rst │ ├── about_py.rst │ ├── debugging.rst │ ├── functions.rst │ ├── getting_started.rst │ ├── index.rst │ ├── index_advanced_python_programming.rst │ ├── index_learning_python.rst │ ├── index_python_scientific_libraries.rst │ ├── index_toc.rst │ ├── matplotlib.rst │ ├── need_for_speed.rst │ ├── numba.rst │ ├── numpy.rst │ ├── oop_intro.rst │ ├── pandas.rst │ ├── parallelization.rst │ ├── python_advanced_features.rst │ ├── python_by_example.rst │ ├── python_essentials.rst │ ├── python_oop.rst │ ├── scipy.rst │ ├── search.rst │ ├── status.rst │ ├── troubleshooting.rst │ └── writing_good_code.rst └── theme └── minimal ├── static ├── css │ ├── base.css │ └── qe.python.css ├── img │ ├── code-block-fade.png │ ├── powered-by-NumFOCUS-orange.svg │ ├── py-logo.png │ ├── qe-logo.png │ ├── search-icon.png │ └── sloan_logo.png ├── js │ └── base.js └── sloan_logo.png └── templates ├── error_report_template.html ├── html.tpl ├── latex.tpl └── latex_book.tpl /.github/workflows/cache.yml: -------------------------------------------------------------------------------- 1 | # !!! 2 | # Once https://github.com/actions/cache/issues/63 is merged 3 | # this can be enabled for daily cache for full HTML previews 4 | # !!! 5 | # name: Build Website Cache (Nightly) 6 | # on: 7 | # schedule: 8 | # - cron: '1 0 * * *' 9 | # jobs: 10 | # build-cache: 11 | # name: Build Website 12 | # runs-on: ubuntu-latest 13 | # steps: 14 | # - name: Checkout 15 | # uses: actions/checkout@v2 16 | # - name: Setup Anaconda 17 | # uses: goanpeca/setup-miniconda@v1 18 | # with: 19 | # auto-update-conda: true 20 | # auto-activate-base: true 21 | # miniconda-version: 'latest' 22 | # python-version: 3.7 23 | # environment-file: environment.yml 24 | # activate-environment: qe-lectures 25 | # - name: Checkout QuantEcon theme 26 | # uses: actions/checkout@v2 27 | # with: 28 | # repository: QuantEcon/lecture-python-programming.theme 29 | # token: ${{ secrets.ACTIONS_PAT }} 30 | # path: theme/lecture-python-programming.theme 31 | # - name: Get current date 32 | # id: date 33 | # run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 34 | # - name: Cache Website Build Folder 35 | # id: cache 36 | # uses: actions/cache@v1 37 | # with: 38 | # path: _build 39 | # key: cache-sphinx-${{ steps.date.outputs.date }} 40 | # - name: Build Website files 41 | # shell: bash -l {0} 42 | # run: | 43 | # make website THEMEPATH=theme/lecture-python-programming.theme 44 | # ls _build/website/jupyter_html/* 45 | 46 | name: Build Website Cache 47 | on: 48 | push: 49 | branches: 50 | - master 51 | jobs: 52 | build-cache: 53 | name: Build Website 54 | runs-on: ubuntu-latest 55 | steps: 56 | - name: Checkout 57 | uses: actions/checkout@v2 58 | - name: Setup Anaconda 59 | uses: conda-incubator/setup-miniconda@v2 60 | with: 61 | auto-update-conda: true 62 | auto-activate-base: true 63 | miniconda-version: 'latest' 64 | python-version: 3.7 65 | environment-file: environment.yml 66 | activate-environment: qe-lectures 67 | - name: Checkout QuantEcon theme 68 | uses: actions/checkout@v2 69 | with: 70 | repository: QuantEcon/lecture-python-programming.theme 71 | token: ${{ secrets.ACTIONS_PAT }} 72 | path: theme/lecture-python-programming.theme 73 | - name: Cache Website Build Folder 74 | id: cache 75 | uses: actions/cache@v1 76 | with: 77 | path: _build 78 | key: cache-sphinx 79 | - name: Build Website files 80 | shell: bash -l {0} 81 | run: | 82 | make website THEMEPATH=theme/lecture-python-programming.theme 83 | ls _build/website/jupyter_html/* -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Execution and Link Checks 2 | on: [pull_request] 3 | jobs: 4 | tests: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout 8 | uses: actions/checkout@v2 9 | - name: Setup Anaconda 10 | uses: goanpeca/setup-miniconda@v1 11 | with: 12 | auto-update-conda: true 13 | auto-activate-base: true 14 | miniconda-version: 'latest' 15 | python-version: 3.7 16 | environment-file: environment.yml 17 | activate-environment: qe-lectures 18 | - name: Get Changed Files 19 | id: files 20 | uses: jitterbit/get-changed-files@v1 21 | - name: Run Execution Tests 22 | shell: bash -l {0} 23 | run: bash scripts/execution-test.sh "${{ steps.files.outputs.added_modified }}" 24 | - name: Run Linkchecker 25 | shell: bash -l {0} 26 | run: bash scripts/linkchecker-test.sh "${{ steps.files.outputs.added_modified }}" -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Execution and Link Testing (Nightly) 2 | on: 3 | schedule: 4 | - cron: '0 17 * * *' 5 | jobs: 6 | coverage: 7 | name: Run Coverage 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2 12 | - name: Setup Anaconda 13 | uses: goanpeca/setup-miniconda@v1 14 | with: 15 | auto-update-conda: true 16 | auto-activate-base: true 17 | miniconda-version: 'latest' 18 | python-version: 3.7 19 | environment-file: environment.yml 20 | activate-environment: qe-lectures 21 | - name: Run Execution Tests 22 | shell: bash -l {0} 23 | run: make coverage 24 | linkchecker: 25 | name: Run linkchecker 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | - name: Setup Anaconda 31 | uses: goanpeca/setup-miniconda@v1 32 | with: 33 | auto-update-conda: true 34 | auto-activate-base: true 35 | miniconda-version: 'latest' 36 | python-version: 3.7 37 | environment-file: environment.yml 38 | activate-environment: qe-lectures 39 | - name: Run Linkchecker 40 | shell: bash -l {0} 41 | run: make linkcheck -------------------------------------------------------------------------------- /.github/workflows/deploy-s3.yml: -------------------------------------------------------------------------------- 1 | # name: Build Website and Deploy to S3 2 | # on: 3 | # push: 4 | # branches: 5 | # - master 6 | # jobs: 7 | # build-cache: 8 | # name: Build Website 9 | # runs-on: ubuntu-latest 10 | # steps: 11 | # - name: Checkout 12 | # uses: actions/checkout@v2 13 | # - name: Setup Anaconda 14 | # uses: goanpeca/setup-miniconda@v1 15 | # with: 16 | # auto-update-conda: true 17 | # auto-activate-base: true 18 | # miniconda-version: 'latest' 19 | # python-version: 3.7 20 | # environment-file: environment.yml 21 | # activate-environment: qe-lectures 22 | # - name: Checkout QuantEcon theme 23 | # uses: actions/checkout@v2 24 | # with: 25 | # repository: QuantEcon/lecture-python-programming.theme 26 | # token: ${{ secrets.ACTIONS_PAT }} 27 | # path: theme/lecture-python-programming.theme 28 | # - name: Build Website files 29 | # shell: bash -l {0} 30 | # run: | 31 | # make website THEMEPATH=theme/lecture-python-programming.theme 32 | # ls _build/website/jupyter_html/* 33 | # - name: Configure AWS credentials 34 | # uses: aws-actions/configure-aws-credentials@v1 35 | # with: 36 | # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 37 | # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 38 | # aws-region: ap-southeast-2 39 | # - name: Copy files to S3 with the AWS CLI 40 | # run: | 41 | # aws s3 sync _build/website/jupyter_html/ s3://test.python.quantecon.org/ -------------------------------------------------------------------------------- /.github/workflows/preview.yml: -------------------------------------------------------------------------------- 1 | name: 'Netlify Preview Deploy' 2 | on: 3 | pull_request: 4 | types: ['opened', 'edited', 'synchronize'] 5 | jobs: 6 | deploy-preview: 7 | name: 'Deploy' 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2 12 | - name: Setup Anaconda 13 | uses: goanpeca/setup-miniconda@v1 14 | with: 15 | auto-update-conda: true 16 | auto-activate-base: true 17 | miniconda-version: 'latest' 18 | python-version: 3.7 19 | environment-file: environment.yml 20 | activate-environment: qe-lectures 21 | - name: Get Changed Files 22 | id: files 23 | uses: jitterbit/get-changed-files@v1 24 | - name: Checkout QuantEcon theme 25 | if: github.event.pull_request.head.repo.full_name == github.repository 26 | uses: actions/checkout@v2 27 | with: 28 | repository: QuantEcon/lecture-python-programming.theme 29 | token: ${{ secrets.ACTIONS_PAT }} 30 | path: theme/lecture-python-programming.theme 31 | # - name: Get current date 32 | # id: date 33 | # run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 34 | - name: Check Sphinx Cache 35 | id: cache 36 | uses: actions/cache@v1 37 | with: 38 | path: _build 39 | key: cache-sphinx 40 | # key: cache-sphinx-${{ steps.date.outputs.date }} 41 | - name: Build website files 42 | shell: bash -l {0} 43 | run: | 44 | bash scripts/build-website.sh "${{ steps.files.outputs.added_modified }}" "${{ github.event.pull_request.head.repo.full_name == github.repository }}" 45 | - name: Preview Deploy to Netlify 46 | uses: nwtgck/actions-netlify@v1.1 47 | if: env.BUILD_NETLIFY == 'true' 48 | with: 49 | publish-dir: './_build/website/jupyter_html' 50 | production-branch: master 51 | github-token: ${{ secrets.GITHUB_TOKEN }} 52 | deploy-message: "Preview Deploy from GitHub Actions" 53 | env: 54 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 55 | NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | dask-worker-space/ 3 | [._]*.s[a-v][a-z] 4 | [._]*.sw[a-p] 5 | [._]s[a-v][a-z] 6 | [._]sw[a-p] 7 | .DS_Store 8 | .DS_Store? 9 | **/.DS_Store 10 | venv/ 11 | theme/lecture-python-programming.theme 12 | .prettierignore -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, QuantEcon 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := bash 2 | # 3 | # Makefile for Sphinx Extension Test Cases 4 | # 5 | 6 | # You can set these variables from the command line. 7 | SPHINXOPTS = -c "./" 8 | SPHINXBUILD = python -msphinx 9 | SPHINXPROJ = lecture-python-programming 10 | SOURCEDIR = source/rst 11 | BUILDDIR = _build 12 | BUILDWEBSITE = _build/website 13 | BUILDCOVERAGE = _build/coverage 14 | BUILDPDF = _build/pdf 15 | PORT = 8890 16 | FILES = 17 | THEMEPATH = theme/minimal 18 | TEMPLATEPATH = $(THEMEPATH)/templates 19 | 20 | # Put it first so that "make" without argument is like "make help". 21 | help: 22 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(FILES) $(SPHINXOPTS) $(O) 23 | 24 | .PHONY: help Makefile 25 | 26 | # Install requiremenets for building lectures. 27 | setup: 28 | pip install -r requirements.txt 29 | 30 | preview: 31 | ifeq (,$(filter $(target),website Website)) 32 | cd $(BUILDWEBSITE)/jupyter_html && python -m http.server $(PORT) 33 | else 34 | ifdef lecture 35 | cd $(BUILDDIR)/jupyter/ && jupyter notebook --port $(PORT) --port-retries=0 $(basename $(lecture)).ipynb 36 | else 37 | cd $(BUILDDIR)/jupyter/ && jupyter notebook --port $(PORT) --port-retries=0 38 | endif 39 | endif 40 | 41 | clean-coverage: 42 | rm -rf $(BUILDCOVERAGE) 43 | 44 | clean-website: 45 | rm -rf $(BUILDWEBSITE) 46 | 47 | clean-pdf: 48 | rm -rf $(BUILDDIR)/jupyterpdf 49 | 50 | coverage: 51 | ifneq ($(strip $(parallel)),) 52 | @$(SPHINXBUILD) -M jupyter "$(SOURCEDIR)" "$(BUILDCOVERAGE)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_make_coverage=1 -D jupyter_execute_notebooks=1 -D jupyter_ignore_skip_test=0 -D jupyter_theme_path="$(THEMEPATH)" -D jupyter_template_path="$(TEMPLATEPATH)" -D jupyter_template_coverage_file_path="error_report_template.html" -D jupyter_number_workers=$(parallel) 53 | else 54 | @$(SPHINXBUILD) -M jupyter "$(SOURCEDIR)" "$(BUILDCOVERAGE)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_make_coverage=1 -D jupyter_execute_notebooks=1 -D jupyter_ignore_skip_test=0 -D jupyter_theme_path="$(THEMEPATH)" -D jupyter_template_path="$(TEMPLATEPATH)" -D jupyter_template_coverage_file_path="error_report_template.html" 55 | endif 56 | 57 | website: 58 | echo "Theme: $(THEMEPATH)" 59 | ifneq ($(strip $(parallel)),) 60 | @$(SPHINXBUILD) -M jupyter "$(SOURCEDIR)" "$(BUILDWEBSITE)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_make_site=1 -D jupyter_generate_html=1 -D jupyter_download_nb=1 -D jupyter_execute_notebooks=1 -D jupyter_target_html=1 -D jupyter_download_nb_image_urlpath="https://s3-ap-southeast-2.amazonaws.com/python-programming.quantecon.org/_static/" -D jupyter_images_markdown=0 -D jupyter_theme_path="$(THEMEPATH)" -D jupyter_template_path="$(TEMPLATEPATH)" -D jupyter_html_template="html.tpl" -D jupyter_download_nb_urlpath="https://python-programming.quantecon.org/" -D jupyter_coverage_dir=$(BUILDCOVERAGE) -D jupyter_number_workers=$(parallel) 61 | 62 | else 63 | @$(SPHINXBUILD) -M jupyter "$(SOURCEDIR)" "$(BUILDWEBSITE)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_make_site=1 -D jupyter_generate_html=1 -D jupyter_download_nb=1 -D jupyter_execute_notebooks=1 -D jupyter_target_html=1 -D jupyter_download_nb_image_urlpath="https://s3-ap-southeast-2.amazonaws.com/python-programming.quantecon.org/_static/" -D jupyter_images_markdown=0 -D jupyter_theme_path="$(THEMEPATH)" -D jupyter_template_path="$(TEMPLATEPATH)" -D jupyter_html_template="html.tpl" -D jupyter_download_nb_urlpath="https://python-programming.quantecon.org/" -D jupyter_coverage_dir=$(BUILDCOVERAGE) 64 | endif 65 | 66 | pdf: 67 | ifneq ($(strip $(parallel)),) 68 | @$(SPHINXBUILD) -M jupyterpdf "$(SOURCEDIR)" "$(BUILDDIR)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_latex_template="latex.tpl" -D jupyter_theme_path="$(THEMEPATH)" -D jupyter_template_path="$(TEMPLATEPATH)" -D jupyter_latex_template_book="latex_book.tpl" -D jupyter_images_markdown=1 -D jupyter_execute_notebooks=1 -D jupyter_pdf_book=1 -D jupyter_target_pdf=1 -D jupyter_number_workers=$(parallel) 69 | 70 | else 71 | @$(SPHINXBUILD) -M jupyterpdf "$(SOURCEDIR)" "$(BUILDDIR)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_theme_path="$(THEMEPATH)" -D jupyter_template_path="$(TEMPLATEPATH)" -D jupyter_latex_template="latex.tpl" -D jupyter_latex_template_book="latex_book.tpl" -D jupyter_images_markdown=1 -D jupyter_execute_notebooks=1 -D jupyter_pdf_book=1 -D jupyter_target_pdf=1 72 | endif 73 | 74 | constructor-pdf: 75 | ifneq ($(strip $(parallel)),) 76 | @$(SPHINXBUILD) -M jupyter "$(SOURCEDIR)" "$(BUILDPDF)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_images_markdown=1 -D jupyter_execute_notebooks=1 -D jupyter_number_workers=$(parallel) 77 | 78 | else 79 | @$(SPHINXBUILD) -M jupyter "$(SOURCEDIR)" "$(BUILDPDF)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_images_markdown=1 -D jupyter_execute_notebooks=1 80 | endif 81 | 82 | notebooks: 83 | make jupyter 84 | 85 | # Catch-all target: route all unknown targets to Sphinx using the new 86 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 87 | %: Makefile 88 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(FILES) $(SPHINXOPTS) $(O) -D jupyter_allow_html_only=1 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lecture-python-programming 2 | 3 | Source files for https://python-programming.quantecon.org 4 | 5 | For a guide on contributing to this repository click [here](https://quantecon.org/contribute-lectures/) 6 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # QuantEcon.lectures-python documentation build configuration file, created by 5 | # sphinx-quickstart on Mon Feb 13 14:28:35 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import sys 17 | import os 18 | import nbformat 19 | import datetime 20 | 21 | now = datetime.datetime.now() 22 | 23 | 24 | # If extensions (or modules to document with autodoc) are in another directory, 25 | # add these directories to sys.path here. If the directory is relative to the 26 | # documentation root, use os.path.abspath to make it absolute, like shown here. 27 | #sys.path.insert(0, os.path.abspath('.')) 28 | 29 | # -- General configuration ------------------------------------------------ 30 | 31 | # If your documentation needs a minimal Sphinx version, state it here. 32 | needs_sphinx = '1.5' 33 | 34 | # Add any Sphinx extension module names here, as strings. They can be 35 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 36 | # ones. 37 | extensions = [ 38 | 'sphinx.ext.mathjax', 39 | 'sphinxcontrib.bibtex', 40 | 'IPython.sphinxext.ipython_console_highlighting', 41 | # Custom Sphinx Extensions 42 | 'sphinxcontrib.jupyter', 43 | ] 44 | 45 | # Retired Extensions but may be useful in Future 46 | 47 | # 'matplotlib.sphinxext.plot_directive', 48 | # 'matplotlib.sphinxext.only_directives', 49 | # 'sphinxcontrib.tikz', 50 | # 'sphinx.ext.graphviz', 51 | 52 | # Add any paths that contain templates here, relative to this directory. 53 | templates_path = ['_templates'] 54 | 55 | # The suffix(es) of source filenames. 56 | # You can specify multiple suffix as a list of string: 57 | # source_suffix = ['.rst', '.md'] 58 | source_suffix = '.rst' 59 | 60 | # The encoding of source files. 61 | #source_encoding = 'utf-8-sig' 62 | 63 | # The master toctree document. 64 | master_doc = 'index' 65 | master_pdf_doc = 'index' 66 | 67 | # General information about the project. 68 | project = 'QuantEcon.lectures-python3' 69 | copyright = '2019, Thomas J. Sargent and John Stachurski' 70 | author = 'Thomas J. Sargent and John Stachurski' 71 | 72 | # The version info for the project you're documenting, acts as replacement for 73 | # |version| and |release|, also used in various other places throughout the 74 | # built documents. 75 | # 76 | # The short X.Y version. 77 | version = '%s-%s-%s' % (now.year, now.strftime("%b"), now.day) 78 | # The full version, including alpha/beta/rc tags. 79 | release = version 80 | 81 | # The language for content autogenerated by Sphinx. Refer to documentation 82 | # for a list of supported languages. 83 | # 84 | # This is also used if you do content translation via gettext catalogs. 85 | # Usually you set "language" from the command line for these cases. 86 | language = None 87 | 88 | # There are two options for replacing |today|: either, you set today to some 89 | # non-false value, then it is used: 90 | #today = '' 91 | # Else, today_fmt is used as the format for a strftime call. 92 | #today_fmt = '%B %d, %Y' 93 | 94 | # List of patterns, relative to source directory, that match files and 95 | # directories to ignore when looking for source files. 96 | exclude_patterns = ['_build', '_static'] 97 | 98 | # The reST default role (used for this markup: `text`) to use for all 99 | # documents. 100 | #default_role = None 101 | 102 | # If true, '()' will be appended to :func: etc. cross-reference text. 103 | #add_function_parentheses = True 104 | 105 | # If true, the current module name will be prepended to all description 106 | # unit titles (such as .. function::). 107 | #add_module_names = True 108 | 109 | # If true, sectionauthor and moduleauthor directives will be shown in the 110 | # output. They are ignored by default. 111 | #show_authors = False 112 | 113 | # The name of the Pygments (syntax highlighting) style to use. 114 | pygments_style = 'sphinx' 115 | 116 | # A list of ignored prefixes for module index sorting. 117 | #modindex_common_prefix = [] 118 | 119 | # If true, keep warnings as "system message" paragraphs in the built documents. 120 | #keep_warnings = False 121 | 122 | # If true, `todo` and `todoList` produce output, else they produce nothing. 123 | todo_include_todos = False 124 | 125 | # Add rst prolog 126 | rst_prolog = """ 127 | .. highlight:: python3 128 | """ 129 | 130 | # -- Options for HTML output ---------------------------------------------- 131 | 132 | # The theme to use for HTML and HTML Help pages. See the documentation for 133 | # a list of builtin themes. 134 | html_theme = 'qe-lectures' 135 | 136 | # Theme options are theme-specific and customize the look and feel of a theme 137 | # further. For a list of options available for each theme, see the 138 | # documentation. 139 | #html_theme_options = {} 140 | 141 | # Add any paths that contain custom themes here, relative to this directory. 142 | html_theme_path = ['_themes'] 143 | 144 | # The name for this set of Sphinx documents. If None, it defaults to 145 | # " v documentation". 146 | html_title = "Quantitative Economics with Python" 147 | 148 | # A shorter title for the navigation bar. Default is the same as html_title. 149 | #html_short_title = None 150 | 151 | # The name of an image file (relative to this directory) to place at the top 152 | # of the sidebar. 153 | #html_logo = None 154 | 155 | # The name of an image file (within the static path) to use as favicon of the 156 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 157 | # pixels large. 158 | #html_favicon = None 159 | 160 | # Add any paths that contain custom static files (such as style sheets) here, 161 | # relative to this directory. They are copied after the builtin static files, 162 | # so a file named "default.css" will overwrite the builtin "default.css". 163 | html_static_path = ['_static'] 164 | 165 | # Add any extra paths that contain custom files (such as robots.txt or 166 | # .htaccess) here, relative to this directory. These files are copied 167 | # directly to the root of the documentation. 168 | #html_extra_path = [] 169 | 170 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 171 | # using the given strftime format. 172 | #html_last_updated_fmt = '%b %d, %Y' 173 | 174 | # If true, SmartyPants will be used to convert quotes and dashes to 175 | # typographically correct entities. 176 | #html_use_smartypants = True 177 | 178 | # Custom sidebar templates, maps document names to template names. 179 | # html_sidebars = { 180 | # 'index': ['py_layout.html'], 181 | # } 182 | 183 | # Additional templates that should be rendered to pages, maps page names to 184 | # template names. 185 | #html_additional_pages = {} 186 | 187 | # If false, no module index is generated. 188 | #html_domain_indices = True 189 | 190 | # If false, no index is generated. 191 | #html_use_index = True 192 | 193 | # If true, the index is split into individual pages for each letter. 194 | #html_split_index = False 195 | 196 | # If true, links to the reST sources are added to the pages. 197 | #html_show_sourcelink = True 198 | 199 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 200 | #html_show_sphinx = True 201 | 202 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 203 | #html_show_copyright = True 204 | 205 | # If true, an OpenSearch description file will be output, and all pages will 206 | # contain a tag referring to it. The value of this option must be the 207 | # base URL from which the finished HTML is served. 208 | #html_use_opensearch = '' 209 | 210 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 211 | #html_file_suffix = None 212 | 213 | # Language to be used for generating the HTML full-text search index. 214 | # Sphinx supports the following languages: 215 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 216 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' 217 | #html_search_language = 'en' 218 | 219 | # A dictionary with options for the search language support, empty by default. 220 | # Now only 'ja' uses this config value 221 | #html_search_options = {'type': 'default'} 222 | 223 | # The name of a javascript file (relative to the configuration directory) that 224 | # implements a search results scorer. If empty, the default will be used. 225 | #html_search_scorer = 'scorer.js' 226 | 227 | # Output file base name for HTML help builder. 228 | htmlhelp_basename = 'QuantEconlectures-python3doc' 229 | 230 | # Tikz HTML configuration for rendering images 231 | tikz_latex_preamble = r""" 232 | \usetikzlibrary{arrows} 233 | \usetikzlibrary{calc} 234 | \usetikzlibrary{intersections} 235 | \usetikzlibrary{decorations} 236 | \usetikzlibrary{decorations.pathreplacing} 237 | """ 238 | 239 | # -- Options for LaTeX output --------------------------------------------- 240 | 241 | latex_elements = { 242 | # The paper size ('letterpaper' or 'a4paper'). 243 | #'papersize': 'letterpaper', 244 | 245 | # The font size ('10pt', '11pt' or '12pt'). 246 | 'pointsize': '11pt', 247 | 248 | # Additional stuff for the LaTeX preamble. 249 | 'preamble': r""" 250 | \usepackage{amsmath, amssymb} 251 | \usepackage{mathrsfs} 252 | 253 | \usepackage{tikz} 254 | \usetikzlibrary{arrows} 255 | \usetikzlibrary{calc} 256 | \usetikzlibrary{intersections} 257 | \usetikzlibrary{decorations} 258 | \usepackage{pgf} 259 | \usepackage{pgfplots} 260 | 261 | 262 | \usepackage{bbm} 263 | \newcommand{\RR}{\mathbbm R} 264 | \newcommand{\NN}{\mathbbm N} 265 | \newcommand{\PP}{\mathbbm P} 266 | \newcommand{\EE}{\mathbbm E \,} 267 | \newcommand{\XX}{\mathbbm X} 268 | \newcommand{\ZZ}{\mathbbm Z} 269 | \newcommand{\QQ}{\mathbbm Q} 270 | 271 | \newcommand{\fF}{\mathcal F} 272 | \newcommand{\dD}{\mathcal D} 273 | \newcommand{\lL}{\mathcal L} 274 | \newcommand{\gG}{\mathcal G} 275 | \newcommand{\hH}{\mathcal H} 276 | \newcommand{\nN}{\mathcal N} 277 | \newcommand{\pP}{\mathcal P} 278 | 279 | \DeclareMathOperator{\trace}{trace} 280 | \DeclareMathOperator{\Var}{Var} 281 | \DeclareMathOperator{\Span}{span} 282 | \DeclareMathOperator{\proj}{proj} 283 | \DeclareMathOperator{\col}{col} 284 | \DeclareMathOperator*{\argmax}{arg\,max} 285 | \DeclareMathOperator*{\argmin}{arg\,min} 286 | 287 | \usepackage{makeidx} 288 | \makeindex 289 | """, 290 | 291 | # Latex figure (float) alignment (Could use 'H' to force the placement of figures) 292 | 'figure_align': 'H',#'htbp', 293 | 294 | #Add Frontmatter before TOC 295 | 'tableofcontents' : r"""\newpage 296 | \thispagestyle{empty} 297 | \chapter*{Preface} 298 | \large 299 | This \textbf{pdf} presents a series of lectures on quantitative economic 300 | modeling, designed and written by \href{http://www.tomsargent.com/}{Thomas J. Sargent} and \href{http://johnstachurski.net}{John Stachurski}. 301 | The primary programming languages are \href{https://www.python.org}{Python} and \href{http://julialang.org/}{Julia}. 302 | You can send feedback to the authors via contact@quantecon.org. 303 | 304 | \vspace{5em} 305 | 306 | \begin{leftbar} 307 | \textbf{Note: You are currently viewing an automatically generated 308 | pdf version of our online lectures,} which are located at 309 | 310 | \vspace{2em} 311 | 312 | \begin{center} 313 | \texttt{https://lectures.quantecon.org} 314 | \end{center} 315 | 316 | \vspace{2em} 317 | 318 | Please visit the website for more information on the aims and scope of the 319 | lectures and the two language options (Julia or Python). 320 | 321 | \vspace{1em} 322 | 323 | Due to automatic generation of this pdf, \textbf{presentation quality is likely 324 | to be lower than that of the website}. 325 | 326 | \end{leftbar} 327 | 328 | \normalsize 329 | 330 | \sphinxtableofcontents 331 | """ 332 | } 333 | 334 | # Grouping the document tree into LaTeX files. List of tuples 335 | # (source start file, target name, title, 336 | # author, documentclass [howto, manual, or own class]). 337 | latex_documents = [ 338 | (master_pdf_doc, 'QuantEconlectures-python3.tex', 'QuantEcon.lectures-python3 PDF', 339 | 'Thomas J. Sargent and John Stachurski', 'manual'), 340 | ] 341 | 342 | # The name of an image file (relative to this directory) to place at the top of 343 | # the title page. 344 | #latex_logo = None 345 | 346 | # For "manual" documents, if this is true, then toplevel headings are parts, 347 | # not chapters. 348 | #latex_use_parts = False 349 | 350 | # If true, show page references after internal links. 351 | #latex_show_pagerefs = False 352 | 353 | # If true, show URL addresses after external links. 354 | #latex_show_urls = False 355 | 356 | # Documents to append as an appendix to all manuals. 357 | #latex_appendices = [] 358 | 359 | # If false, no module index is generated. 360 | #latex_domain_indices = True 361 | 362 | # ------------------ 363 | # Linkcheck Options 364 | # ------------------ 365 | 366 | linkcheck_ignore = [r'https:\/\/github\.com\/.*?#.*'] #Anchors on Github seem to create issues with linkchecker 367 | 368 | linkcheck_timeout = 30 369 | 370 | # -------------------------------------------- 371 | # jupyter Sphinx Extension conversion settings 372 | # -------------------------------------------- 373 | 374 | # Conversion Mode Settings 375 | # If "all", convert codes and texts into notebook 376 | # If "code", convert codes only 377 | jupyter_conversion_mode = "all" 378 | 379 | jupyter_write_metadata = False 380 | 381 | # Location for _static folder 382 | jupyter_static_file_path = ["source/_static", "_static"] 383 | 384 | # Configure Jupyter Kernels 385 | jupyter_kernels = { 386 | "python3": { 387 | "kernelspec": { 388 | "display_name": "Python", 389 | "language": "python3", 390 | "name": "python3" 391 | }, 392 | "file_extension": ".py", 393 | }, 394 | } 395 | 396 | # Configure jupyter headers 397 | jupyter_headers = { 398 | "python3": [ 399 | # nbformat.v4.new_code_cell("%autosave 0") #@mmcky please make this an option 400 | ], 401 | "julia": [ 402 | ], 403 | } 404 | 405 | # Filename for the file containing the welcome block 406 | jupyter_welcome_block = "" 407 | 408 | #Adjust links to target html (rather than ipynb) 409 | jupyter_target_html = False 410 | 411 | #path to download notebooks from 412 | jupyter_download_nb_urlpath = None 413 | 414 | #allow downloading of notebooks 415 | jupyter_download_nb = False 416 | 417 | #Use urlprefix images 418 | jupyter_download_nb_image_urlpath = None 419 | 420 | #Allow ipython as a language synonym for blocks to be ipython highlighted 421 | jupyter_lang_synonyms = ["ipython", "ipython3"] 422 | 423 | #Execute skip-test code blocks for rendering of website (this will need to be ignored in coverage testing) 424 | jupyter_ignore_skip_test = True 425 | 426 | #allow execution of notebooks 427 | jupyter_execute_notebooks = False 428 | 429 | # Location of template folder for coverage reports 430 | jupyter_template_coverage_file_path = False 431 | 432 | # generate html from IPYNB files 433 | jupyter_generate_html = False 434 | 435 | # html template specific to your website needs 436 | jupyter_html_template = "" 437 | 438 | # latex template specific to your website needs 439 | jupyter_latex_template = "" 440 | 441 | #make website 442 | jupyter_make_site = False 443 | 444 | #force markdown image inclusion 445 | jupyter_images_markdown = True 446 | 447 | #This is set true by default to pass html to the notebooks 448 | jupyter_allow_html_only=True 449 | 450 | ## Theme specific variables 451 | # jupyter_theme_path = 'theme/minimal' #Specified in Makefile 452 | # jupyter_template_path = 'theme/minimal/templates' #Specified in Makefile 453 | 454 | jupyter_nextprev_ignore = ['404', "search", "status", "troubleshooting"] 455 | 456 | ### pdf options 457 | jupyter_pdf_logo = "_static/img/qe-menubar-logo.png" 458 | 459 | jupyter_bib_file = "_static/quant-econ" 460 | 461 | jupyter_pdf_author = "Thomas J. Sargent and John Stachurski" 462 | 463 | # Exclude Document Patterns for PDF Construction 464 | jupyter_pdf_excludepatterns = ["404", "index", "references"] 465 | 466 | # Set urlpath for html links in documents 467 | jupyter_pdf_urlpath = "https://python-programming.quantecon.org/" 468 | 469 | # make book 470 | jupyter_pdf_book = False 471 | 472 | # book title 473 | jupyter_pdf_book_title = "Python Programming for Economics and Finance" 474 | 475 | # pdf book name 476 | jupyter_pdf_book_name = "python_programming_for_economics_finance" 477 | 478 | # pdf toc file 479 | jupyter_pdf_book_index = "index_toc" 480 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: qe-lectures 2 | channels: 3 | - default 4 | dependencies: 5 | - python=3.7 6 | - anaconda=2020.02 7 | - pip 8 | - pip: 9 | - interpolation 10 | - sphinxcontrib-jupyter 11 | - sphinxcontrib-bibtex==1.0 12 | - joblib -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | sphinxcontrib-bibtex 2 | sphinxcontrib-jupyter 3 | quantecon -------------------------------------------------------------------------------- /scripts/build-website.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MODIFIED_FILES="$1" 4 | PRIVATE_THEME=$2 5 | 6 | RST_FILES="" 7 | for F in $MODIFIED_FILES 8 | do 9 | if [[ $F == *.rst ]] 10 | then 11 | RST_FILES="$RST_FILES $F" 12 | fi 13 | done 14 | echo "List of Changed RST Files: $RST_FILES" 15 | echo "Building with Private theme: $PRIVATE_THEME" 16 | if [ -z "$RST_FILES" ]; then 17 | echo "::set-env name=BUILD_NETLIFY::false" 18 | echo "No RST Files have changed -- nothing to do in this PR" 19 | else 20 | echo "::set-env name=BUILD_NETLIFY::true" 21 | RST_FILES="$RST_FILES source/rst/index_toc.rst" 22 | if [ "$PRIVATE_THEME" = true ]; then 23 | make website THEMEPATH=theme/lecture-python-programming.theme FILES="$RST_FILES" 24 | else 25 | make website FILES="$RST_FILES" 26 | fi 27 | ls _build/website/jupyter_html/* #Ensure build files are created 28 | fi -------------------------------------------------------------------------------- /scripts/execution-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CLEAN_BUILD=false 4 | MODIFIED_FILES="$1" 5 | 6 | RST_FILES="" 7 | for F in $MODIFIED_FILES 8 | do 9 | if [[ $F == environment.yml ]] 10 | then 11 | CLEAN_BUILD=true 12 | break 13 | fi 14 | #Extract List of RST Files 15 | if [[ $F == *.rst ]] 16 | then 17 | RST_FILES="$RST_FILES $F" 18 | fi 19 | done 20 | 21 | echo "List of Changed RST Files: $RST_FILES" 22 | echo "Clean Build Requested: $CLEAN_BUILD" 23 | 24 | if [ "$CLEAN_BUILD" = true ] 25 | then 26 | echo "Running Clean Build" 27 | make coverage 28 | elif [ -z "$RST_FILES" ] 29 | then 30 | echo "No RST Files have changed -- nothing to do in this PR" 31 | else 32 | RST_FILES="$RST_FILES source/rst/index_toc.rst" 33 | echo "Running Selecting Build with: $RST_FILES" 34 | make coverage FILES="$RST_FILES" 35 | fi -------------------------------------------------------------------------------- /scripts/linkchecker-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MODIFIED_FILES="$1" 4 | 5 | RST_FILES="" 6 | for F in $MODIFIED_FILES 7 | do 8 | if [[ $F == *.rst ]] 9 | then 10 | RST_FILES="$RST_FILES $F" 11 | fi 12 | done 13 | echo "List of Changed RST Files: $RST_FILES" 14 | if [ -z "$RST_FILES" ]; then 15 | echo "No RST Files have changed -- nothing to do in this PR" 16 | else 17 | RST_FILES="$RST_FILES source/rst/index_toc.rst" 18 | make linkcheck FILES="$RST_FILES" 19 | fi -------------------------------------------------------------------------------- /scripts/travis-coverage.sh: -------------------------------------------------------------------------------- 1 | echo "PR: $TRAVIS_PULL_REQUEST" 2 | echo "COMMIT RANGE: $TRAVIS_COMMIT_RANGE" 3 | CHANGED_FILES=$(git diff --name-only $TRAVIS_COMMIT_RANGE | grep '\.rst' | tr '\n' ' ') 4 | #Check for Full Deletions 5 | SPHINX_FILES="" 6 | for f in $CHANGED_FILES 7 | do 8 | if [ -f $f ] 9 | then 10 | SPHINX_FILES="$SPHINX_FILES $f" 11 | fi 12 | done 13 | echo "List of Changed Files: $SPHINX_FILES" 14 | if [ -z "$SPHINX_FILES" ]; then 15 | echo "No RST Files have changed -- nothing to do in this PR" 16 | else 17 | make coverage FILES="$SPHINX_FILES" 18 | make linkcheck FILES="$SPHINX_FILES" 19 | fi -------------------------------------------------------------------------------- /sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | https://python-programming.quantecon.org/ 12 | 2020-03-27T00:01:43+00:00 13 | 1.00 14 | 15 | 16 | https://python-programming.quantecon.org/index_toc.html 17 | 2020-03-27T00:01:43+00:00 18 | 0.80 19 | 20 | 21 | https://python-programming.quantecon.org/_downloads/pdf/python_programming_for_quantitative_economics.pdf 22 | 2020-03-26T23:54:05+00:00 23 | 0.80 24 | 25 | 26 | https://python-programming.quantecon.org/about_lectures.html 27 | 2020-03-27T00:01:43+00:00 28 | 0.64 29 | 30 | 31 | https://python-programming.quantecon.org/index_learning_python.html 32 | 2020-03-27T00:01:43+00:00 33 | 0.64 34 | 35 | 36 | https://python-programming.quantecon.org/about_py.html 37 | 2020-03-27T00:01:43+00:00 38 | 0.64 39 | 40 | 41 | https://python-programming.quantecon.org/getting_started.html 42 | 2020-03-27T00:01:43+00:00 43 | 0.64 44 | 45 | 46 | https://python-programming.quantecon.org/python_by_example.html 47 | 2020-03-27T00:01:43+00:00 48 | 0.64 49 | 50 | 51 | https://python-programming.quantecon.org/functions.html 52 | 2020-03-27T00:01:43+00:00 53 | 0.64 54 | 55 | 56 | https://python-programming.quantecon.org/python_essentials.html 57 | 2020-03-27T00:01:43+00:00 58 | 0.64 59 | 60 | 61 | https://python-programming.quantecon.org/oop_intro.html 62 | 2020-03-27T00:01:43+00:00 63 | 0.64 64 | 65 | 66 | https://python-programming.quantecon.org/python_oop.html 67 | 2020-03-27T00:01:43+00:00 68 | 0.64 69 | 70 | 71 | https://python-programming.quantecon.org/index_python_scientific_libraries.html 72 | 2020-03-27T00:01:43+00:00 73 | 0.64 74 | 75 | 76 | https://python-programming.quantecon.org/need_for_speed.html 77 | 2020-03-27T00:01:43+00:00 78 | 0.64 79 | 80 | 81 | https://python-programming.quantecon.org/numpy.html 82 | 2020-03-27T00:01:43+00:00 83 | 0.64 84 | 85 | 86 | https://python-programming.quantecon.org/matplotlib.html 87 | 2020-03-27T00:01:43+00:00 88 | 0.64 89 | 90 | 91 | https://python-programming.quantecon.org/scipy.html 92 | 2020-03-27T00:01:43+00:00 93 | 0.64 94 | 95 | 96 | https://python-programming.quantecon.org/numba.html 97 | 2020-03-27T00:01:43+00:00 98 | 0.64 99 | 100 | 101 | https://python-programming.quantecon.org/parallelization.html 102 | 2020-03-27T00:01:43+00:00 103 | 0.64 104 | 105 | 106 | https://python-programming.quantecon.org/pandas.html 107 | 2020-03-27T00:01:43+00:00 108 | 0.64 109 | 110 | 111 | https://python-programming.quantecon.org/index_advanced_python_programming.html 112 | 2020-03-27T00:01:43+00:00 113 | 0.64 114 | 115 | 116 | https://python-programming.quantecon.org/writing_good_code.html 117 | 2020-03-27T00:01:43+00:00 118 | 0.64 119 | 120 | 121 | https://python-programming.quantecon.org/python_advanced_features.html 122 | 2020-03-27T00:01:43+00:00 123 | 0.64 124 | 125 | 126 | https://python-programming.quantecon.org/debugging.html 127 | 2020-03-27T00:01:43+00:00 128 | 0.64 129 | 130 | 131 | https://python-programming.quantecon.org/_downloads/pdf/about_lectures.pdf 132 | 2020-03-26T23:54:05+00:00 133 | 0.51 134 | 135 | 136 | https://python-programming.quantecon.org/troubleshooting.html 137 | 2020-03-27T00:01:43+00:00 138 | 0.51 139 | 140 | 141 | https://python-programming.quantecon.org/_downloads/pdf/about_py.pdf 142 | 2020-03-26T23:54:05+00:00 143 | 0.51 144 | 145 | 146 | https://python-programming.quantecon.org/_downloads/pdf/getting_started.pdf 147 | 2020-03-26T23:54:05+00:00 148 | 0.51 149 | 150 | 151 | https://python-programming.quantecon.org/_downloads/pdf/python_by_example.pdf 152 | 2020-03-26T23:54:05+00:00 153 | 0.51 154 | 155 | 156 | https://python-programming.quantecon.org/_downloads/pdf/functions.pdf 157 | 2020-03-26T23:54:05+00:00 158 | 0.51 159 | 160 | 161 | https://python-programming.quantecon.org/_downloads/pdf/python_essentials.pdf 162 | 2020-03-26T23:54:05+00:00 163 | 0.51 164 | 165 | 166 | https://python-programming.quantecon.org/_downloads/pdf/oop_intro.pdf 167 | 2020-03-26T23:54:05+00:00 168 | 0.51 169 | 170 | 171 | https://python-programming.quantecon.org/_downloads/pdf/python_oop.pdf 172 | 2020-03-26T23:54:05+00:00 173 | 0.51 174 | 175 | 176 | https://python-programming.quantecon.org/_downloads/pdf/need_for_speed.pdf 177 | 2020-03-26T23:54:05+00:00 178 | 0.51 179 | 180 | 181 | https://python-programming.quantecon.org/_downloads/pdf/numpy.pdf 182 | 2020-03-26T23:54:05+00:00 183 | 0.51 184 | 185 | 186 | https://python-programming.quantecon.org/_downloads/pdf/matplotlib.pdf 187 | 2020-03-26T23:54:05+00:00 188 | 0.51 189 | 190 | 191 | https://python-programming.quantecon.org/_downloads/pdf/scipy.pdf 192 | 2020-03-26T23:54:05+00:00 193 | 0.51 194 | 195 | 196 | https://python-programming.quantecon.org/_downloads/pdf/numba.pdf 197 | 2020-03-26T23:54:05+00:00 198 | 0.51 199 | 200 | 201 | https://python-programming.quantecon.org/_downloads/pdf/parallelization.pdf 202 | 2020-03-26T23:54:05+00:00 203 | 0.51 204 | 205 | 206 | https://python-programming.quantecon.org/_downloads/pdf/pandas.pdf 207 | 2020-03-26T23:54:05+00:00 208 | 0.51 209 | 210 | 211 | https://python-programming.quantecon.org/_downloads/pdf/writing_good_code.pdf 212 | 2020-03-26T23:54:05+00:00 213 | 0.51 214 | 215 | 216 | https://python-programming.quantecon.org/_downloads/pdf/python_advanced_features.pdf 217 | 2020-03-26T23:54:05+00:00 218 | 0.51 219 | 220 | 221 | https://python-programming.quantecon.org/_downloads/pdf/debugging.pdf 222 | 2020-03-26T23:54:05+00:00 223 | 0.51 224 | 225 | 226 | https://python-programming.quantecon.org/_downloads/pdf/troubleshooting.pdf 227 | 2020-03-26T23:54:05+00:00 228 | 0.41 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /source/_static/includes/header.raw: -------------------------------------------------------------------------------- 1 | .. raw:: html 2 | 3 |
4 | 5 | QuantEcon 6 | 7 |
8 | -------------------------------------------------------------------------------- /source/_static/includes/lecture_howto_py.raw: -------------------------------------------------------------------------------- 1 | .. raw:: html 2 | 3 |
4 | 5 | QuantEcon 6 | 7 |
8 | -------------------------------------------------------------------------------- /source/_static/lecture_specific/about_py/bn_density1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/about_py/bn_density1.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/about_py/career_vf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/about_py/career_vf.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/about_py/pandas_vs_matlab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/about_py/pandas_vs_matlab.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/about_py/python_vs_matlab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/about_py/python_vs_matlab.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/about_py/qs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/about_py/qs.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/about_py/qs.py: -------------------------------------------------------------------------------- 1 | 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | from scipy.stats import norm 5 | from matplotlib import cm 6 | 7 | xmin, xmax = -4, 12 8 | x = 10 9 | α = 0.5 10 | 11 | m, v = x, 10 12 | 13 | xgrid = np.linspace(xmin, xmax, 200) 14 | 15 | fig, ax = plt.subplots() 16 | 17 | ax.spines['right'].set_color('none') 18 | ax.spines['top'].set_color('none') 19 | ax.spines['left'].set_color('none') 20 | ax.xaxis.set_ticks_position('bottom') 21 | ax.spines['bottom'].set_position(('data', 0)) 22 | 23 | ax.set_ylim(-0.05, 0.5) 24 | ax.set_xticks((x,)) 25 | ax.set_xticklabels((r'$x$', ), fontsize=18) 26 | ax.set_yticks(()) 27 | 28 | K = 3 29 | for i in range(K): 30 | m = α * m 31 | v = α * α * v + 1 32 | f = norm(loc=m, scale=np.sqrt(v)) 33 | k = (i + 0.5) / K 34 | ax.plot(xgrid, f.pdf(xgrid), lw=1, color='black', alpha=0.4) 35 | ax.fill_between(xgrid, 0 * xgrid, f.pdf(xgrid), color=cm.jet(k), alpha=0.4) 36 | 37 | 38 | ax.annotate(r'$Q(x,\cdot)$', xy=(6.6, 0.2), xycoords='data', 39 | xytext=(20, 90), textcoords='offset points', fontsize=16, 40 | arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=-0.2")) 41 | ax.annotate(r'$Q^2(x,\cdot)$', xy=(3.6, 0.24), xycoords='data', 42 | xytext=(20, 90), textcoords='offset points', fontsize=16, 43 | arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=-0.2")) 44 | ax.annotate(r'$Q^3(x,\cdot)$', xy=(-0.2, 0.28), xycoords='data', 45 | xytext=(-90, 90), textcoords='offset points', fontsize=16, 46 | arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=0.2")) 47 | fig.show() 48 | -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/editing_vim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/editing_vim.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/ipython_shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/ipython_shell.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/jp_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/jp_demo.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb2.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb3.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb6.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb6a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb6a.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb7.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb8.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb_run.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb_upload.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/nb_wntest2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/nb_wntest2.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/getting_started/starting_nb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/getting_started/starting_nb.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/matplotlib/matplotlib_ex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/matplotlib/matplotlib_ex1.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/pandas/data/test_pwt.csv: -------------------------------------------------------------------------------- 1 | "country","country isocode","year","POP","XRAT","tcgdp","cc","cg" 2 | "Argentina","ARG","2000","37335.653","0.9995","295072.21869","75.716805379","5.5788042896" 3 | "Australia","AUS","2000","19053.186","1.72483","541804.6521","67.759025993","6.7200975332" 4 | "India","IND","2000","1006300.297","44.9416","1728144.3748","64.575551328","14.072205773" 5 | "Israel","ISR","2000","6114.57","4.07733","129253.89423","64.436450847","10.266688415" 6 | "Malawi","MWI","2000","11801.505","59.543808333","5026.2217836","74.707624181","11.658954494" 7 | "South Africa","ZAF","2000","45064.098","6.93983","227242.36949","72.718710427","5.7265463933" 8 | "United States","USA","2000","282171.957","1","9898700","72.347054303","6.0324539789" 9 | "Uruguay","URY","2000","3219.793","12.099591667","25255.961693","78.978740282","5.108067988" 10 | -------------------------------------------------------------------------------- /source/_static/lecture_specific/pandas/pandas_indices_pctchange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/pandas/pandas_indices_pctchange.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/pandas/pandas_share_prices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/pandas/pandas_share_prices.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/pandas/pandas_vs_rest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/pandas/pandas_vs_rest.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/pandas/wb_download.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import requests 3 | import pandas as pd 4 | 5 | # == Get data and read into file gd.xls == # 6 | wb_data_query = "http://api.worldbank.org/v2/en/indicator/gc.dod.totl.gd.zs?downloadformat=excel" 7 | r = requests.get(wb_data_query) 8 | with open('gd.xls', 'wb') as output: 9 | output.write(r.content) 10 | 11 | # == Parse data into a DataFrame == # 12 | govt_debt = pd.read_excel('gd.xls', sheet_name='Data', skiprows=3, index_col=1) 13 | 14 | # == Take desired values and plot == # 15 | govt_debt = govt_debt.transpose() 16 | govt_debt = govt_debt[['AUS', 'USA']] 17 | govt_debt = govt_debt[38:] 18 | govt_debt.plot(lw=2) 19 | plt.show() 20 | -------------------------------------------------------------------------------- /source/_static/lecture_specific/parallelization/htop_parallel_npmat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/parallelization/htop_parallel_npmat.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/python_advanced_features/numbers.txt: -------------------------------------------------------------------------------- 1 | prices 2 | 3 3 | 8 4 | 5 | 7 6 | 21 -------------------------------------------------------------------------------- /source/_static/lecture_specific/python_by_example/pbe_ex2_fig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/python_by_example/pbe_ex2_fig.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/python_by_example/test_program_1_updated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/python_by_example/test_program_1_updated.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/python_foundations/us_cities.txt: -------------------------------------------------------------------------------- 1 | new york: 8244910 2 | los angeles: 3819702 3 | chicago: 2707120 4 | houston: 2145146 5 | philadelphia: 1536471 6 | phoenix: 1469471 7 | san antonio: 1359758 8 | san diego: 1326179 9 | dallas: 1223229 10 | -------------------------------------------------------------------------------- /source/_static/lecture_specific/sci_libs/nfs_ex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/sci_libs/nfs_ex1.png -------------------------------------------------------------------------------- /source/_static/lecture_specific/troubleshooting/launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/lecture_specific/troubleshooting/launch.png -------------------------------------------------------------------------------- /source/_static/qe-logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/source/_static/qe-logo-large.png -------------------------------------------------------------------------------- /source/rst/.ipynb_checkpoints/Untitled-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import glob\n", 10 | "import re\n", 11 | "import os\n", 12 | "import errno\n", 13 | "path1 = '/home/anju/Documents/lecture-source-py/source/rst/*.rst'\n", 14 | "path2 = '*.tex'\n", 15 | "path = '*.rst'\n", 16 | "files = glob.glob(path)" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "def func_replace(a, b, filename):\n", 26 | " with open(filename,'r+', encoding=\"utf8\") as f:\n", 27 | " #convert to string:\n", 28 | " data = f.read()\n", 29 | " f.seek(0)\n", 30 | " f.write(data.replace(a, b))\n", 31 | " f.truncate()" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "def replace(srr, name):\n", 41 | " \n", 42 | " func_replace(\"_static/figures/\", \"_static/lecture_specific/\"+srr+\"/\", name)\n", 43 | " \n", 44 | " func_replace(\"_static/code/\", \"_static/lecture_specific/\", name)\n", 45 | " \n", 46 | " func_replace(\"_static/pdfs/\", \"_static/lecture_specific/\"+srr+\"/\", name)" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "count=0\n", 56 | "for name in files:\n", 57 | " #name = \"von_neumann_model.tex\"\n", 58 | " srr =\"\"\n", 59 | " srr += name[0:len(name)-4]\n", 60 | " print(srr+\"\\n\")\n", 61 | " count+=1\n", 62 | " replace(srr,name)\n", 63 | " #make_changes(name)\n", 64 | " #sections_name(name)\n", 65 | " #func_replace(name[0:len(name)-4]+\"}\"+\"\\n\"+\" \\\\end{itemize}\"+\"\\n\"+\"\\\\end{itemize}\", name[0:len(name)-4]+\"}\"+\"\\n\"+\" \\\\end{itemize}\",name)\n", 66 | "\n", 67 | "print(count)" 68 | ] 69 | } 70 | ], 71 | "metadata": { 72 | "kernelspec": { 73 | "display_name": "Python 3", 74 | "language": "python", 75 | "name": "python3" 76 | }, 77 | "language_info": { 78 | "codemirror_mode": { 79 | "name": "ipython", 80 | "version": 3 81 | }, 82 | "file_extension": ".py", 83 | "mimetype": "text/x-python", 84 | "name": "python", 85 | "nbconvert_exporter": "python", 86 | "pygments_lexer": "ipython3", 87 | "version": "3.7.3" 88 | } 89 | }, 90 | "nbformat": 4, 91 | "nbformat_minor": 2 92 | } 93 | -------------------------------------------------------------------------------- /source/rst/.ipynb_checkpoints/changethis-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import glob\n", 10 | "import re\n", 11 | "import os\n", 12 | "import errno\n", 13 | "path1 = '/home/anju/Documents/lecture-source-py/source/rst/*.rst'\n", 14 | "path2 = '*.tex'\n", 15 | "path = '*.rst'\n", 16 | "files = glob.glob(path)" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 6, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "def func_replace(a, b, filename):\n", 26 | " with open(filename,'r+', encoding=\"utf8\") as f:\n", 27 | " #convert to string:\n", 28 | " data = f.read()\n", 29 | " f.seek(0)\n", 30 | " f.write(data.replace(a, b))\n", 31 | " f.truncate()" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 7, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "def replace(srr, name):\n", 41 | " \n", 42 | " func_replace(\"_static/figures/\", \"_static/lecture_specific/\"+srr+\"/\", name)\n", 43 | " \n", 44 | " func_replace(\"_static/code/\", \"_static/lecture_specific/\", name)\n", 45 | " \n", 46 | " func_replace(\"_static/pdfs/\", \"_static/lecture_specific/\"+srr+\"/\", name)" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 8, 52 | "metadata": {}, 53 | "outputs": [ 54 | { 55 | "name": "stdout", 56 | "output_type": "stream", 57 | "text": [ 58 | "classical_filtering\n", 59 | "\n", 60 | "coase\n", 61 | "\n", 62 | "coleman_policy_iter\n", 63 | "\n", 64 | "amss\n", 65 | "\n", 66 | "amss2\n", 67 | "\n", 68 | "amss3\n", 69 | "\n", 70 | "complex_and_trig\n", 71 | "\n", 72 | "arma\n", 73 | "\n", 74 | "cass_koopmans\n", 75 | "\n", 76 | "arellano\n", 77 | "\n", 78 | "career\n", 79 | "\n", 80 | "chang_ramsey\n", 81 | "\n", 82 | "chang_credible\n", 83 | "\n", 84 | "cattle_cycles\n", 85 | "\n", 86 | "calvo\n", 87 | "\n", 88 | "black_litterman\n", 89 | "\n", 90 | "16\n" 91 | ] 92 | } 93 | ], 94 | "source": [ 95 | "count=0\n", 96 | "for name in files:\n", 97 | " #name = \"von_neumann_model.tex\"\n", 98 | " srr =\"\"\n", 99 | " srr += name[0:len(name)-4]\n", 100 | " print(srr+\"\\n\")\n", 101 | " count+=1\n", 102 | " replace(srr,name)\n", 103 | " #make_changes(name)\n", 104 | " #sections_name(name)\n", 105 | " #func_replace(name[0:len(name)-4]+\"}\"+\"\\n\"+\" \\\\end{itemize}\"+\"\\n\"+\"\\\\end{itemize}\", name[0:len(name)-4]+\"}\"+\"\\n\"+\" \\\\end{itemize}\",name)\n", 106 | "\n", 107 | "print(count)" 108 | ] 109 | } 110 | ], 111 | "metadata": { 112 | "kernelspec": { 113 | "display_name": "Python 3", 114 | "language": "python", 115 | "name": "python3" 116 | }, 117 | "language_info": { 118 | "codemirror_mode": { 119 | "name": "ipython", 120 | "version": 3 121 | }, 122 | "file_extension": ".py", 123 | "mimetype": "text/x-python", 124 | "name": "python", 125 | "nbconvert_exporter": "python", 126 | "pygments_lexer": "ipython3", 127 | "version": "3.7.3" 128 | } 129 | }, 130 | "nbformat": 4, 131 | "nbformat_minor": 2 132 | } 133 | -------------------------------------------------------------------------------- /source/rst/404.rst: -------------------------------------------------------------------------------- 1 | .. _404: 2 | 3 | *************** 4 | Page Not Found 5 | *************** 6 | 7 | .. raw:: html 8 | 9 | 10 | 11 | 12 | We couldn’t find the page you were looking for. 13 | 14 | Please check the URL or try a link below: 15 | 16 | * `Home `_ 17 | * `QuantEcon `_ 18 | * `Quantitative Economics with Python `_ 19 | * `Quantitative Economics with Julia `_ 20 | * `QuantEcon DataScience `_ 21 | * `Forum `_ 22 | * `Contact us `_ -------------------------------------------------------------------------------- /source/rst/_static: -------------------------------------------------------------------------------- 1 | ../_static -------------------------------------------------------------------------------- /source/rst/about_lectures.rst: -------------------------------------------------------------------------------- 1 | ************** 2 | About Lectures 3 | ************** 4 | 5 | This is one of a series of online texts on modern quantitative 6 | economics and programming with Python. This is the first 7 | text in the series, which focuses on programming in Python. 8 | 9 | For an overview of the series, see `this page `__ -------------------------------------------------------------------------------- /source/rst/debugging.rst: -------------------------------------------------------------------------------- 1 | .. _debugging: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | *********************************** 6 | Debugging 7 | *********************************** 8 | 9 | .. index:: 10 | single: Debugging 11 | 12 | .. contents:: :depth: 2 13 | 14 | .. epigraph:: 15 | 16 | "Debugging is twice as hard as writing the code in the first place. 17 | Therefore, if you write the code as cleverly as possible, you are, by definition, 18 | not smart enough to debug it." -- Brian Kernighan 19 | 20 | 21 | 22 | Overview 23 | =========== 24 | 25 | 26 | Are you one of those programmers who fills their code with ``print`` statements when trying to debug their programs? 27 | 28 | Hey, we all used to do that. 29 | 30 | (OK, sometimes we still do that...) 31 | 32 | But once you start writing larger programs you'll need a better system. 33 | 34 | Debugging tools for Python vary across platforms, IDEs and editors. 35 | 36 | Here we'll focus on Jupyter and leave you to explore other settings. 37 | 38 | We'll need the following imports 39 | 40 | .. code-block:: ipython 41 | 42 | import numpy as np 43 | import matplotlib.pyplot as plt 44 | %matplotlib inline 45 | 46 | 47 | Debugging 48 | ============ 49 | 50 | .. index:: 51 | single: Debugging 52 | 53 | 54 | The ``debug`` Magic 55 | ---------------------- 56 | 57 | Let's consider a simple (and rather contrived) example 58 | 59 | .. code-block:: ipython 60 | :class: skip-test 61 | 62 | def plot_log(): 63 | fig, ax = plt.subplots(2, 1) 64 | x = np.linspace(1, 2, 10) 65 | ax.plot(x, np.log(x)) 66 | plt.show() 67 | 68 | plot_log() # Call the function, generate plot 69 | 70 | 71 | This code is intended to plot the ``log`` function over the interval :math:`[1, 2]`. 72 | 73 | But there's an error here: ``plt.subplots(2, 1)`` should be just ``plt.subplots()``. 74 | 75 | (The call ``plt.subplots(2, 1)`` returns a NumPy array containing two axes objects, suitable for having two subplots on the same figure) 76 | 77 | The traceback shows that the error occurs at the method call ``ax.plot(x, np.log(x))``. 78 | 79 | The error occurs because we have mistakenly made ``ax`` a NumPy array, and a NumPy array has no ``plot`` method. 80 | 81 | But let's pretend that we don't understand this for the moment. 82 | 83 | We might suspect there's something wrong with ``ax`` but when we try to investigate this object, we get the following exception: 84 | 85 | .. code-block:: python3 86 | :class: skip-test 87 | 88 | ax 89 | 90 | The problem is that ``ax`` was defined inside ``plot_log()``, and the name is 91 | lost once that function terminates. 92 | 93 | Let's try doing it a different way. 94 | 95 | We run the first cell block again, generating the same error 96 | 97 | .. code-block:: python3 98 | :class: skip-test 99 | 100 | def plot_log(): 101 | fig, ax = plt.subplots(2, 1) 102 | x = np.linspace(1, 2, 10) 103 | ax.plot(x, np.log(x)) 104 | plt.show() 105 | 106 | plot_log() # Call the function, generate plot 107 | 108 | 109 | But this time we type in the following cell block 110 | 111 | .. code-block:: ipython 112 | :class: no-execute 113 | 114 | %debug 115 | 116 | You should be dropped into a new prompt that looks something like this 117 | 118 | .. code-block:: ipython 119 | :class: no-execute 120 | 121 | ipdb> 122 | 123 | (You might see `pdb>` instead) 124 | 125 | Now we can investigate the value of our variables at this point in the program, step forward through the code, etc. 126 | 127 | For example, here we simply type the name ``ax`` to see what's happening with 128 | this object: 129 | 130 | .. code-block:: ipython 131 | :class: no-execute 132 | 133 | ipdb> ax 134 | array([, 135 | ], dtype=object) 136 | 137 | It's now very clear that ``ax`` is an array, which clarifies the source of the 138 | problem. 139 | 140 | To find out what else you can do from inside ``ipdb`` (or ``pdb``), use the 141 | online help 142 | 143 | .. code-block:: ipython 144 | :class: no-execute 145 | 146 | ipdb> h 147 | 148 | Documented commands (type help ): 149 | ======================================== 150 | EOF bt cont enable jump pdef r tbreak w 151 | a c continue exit l pdoc restart u whatis 152 | alias cl d h list pinfo return unalias where 153 | args clear debug help n pp run unt 154 | b commands disable ignore next q s until 155 | break condition down j p quit step up 156 | 157 | Miscellaneous help topics: 158 | ========================== 159 | exec pdb 160 | 161 | Undocumented commands: 162 | ====================== 163 | retval rv 164 | 165 | ipdb> h c 166 | c(ont(inue)) 167 | Continue execution, only stop when a breakpoint is encountered. 168 | 169 | 170 | Setting a Break Point 171 | ---------------------- 172 | 173 | The preceding approach is handy but sometimes insufficient. 174 | 175 | Consider the following modified version of our function above 176 | 177 | .. code-block:: python3 178 | :class: skip-test 179 | 180 | def plot_log(): 181 | fig, ax = plt.subplots() 182 | x = np.logspace(1, 2, 10) 183 | ax.plot(x, np.log(x)) 184 | plt.show() 185 | 186 | plot_log() 187 | 188 | Here the original problem is fixed, but we've accidentally written 189 | ``np.logspace(1, 2, 10)`` instead of ``np.linspace(1, 2, 10)``. 190 | 191 | Now there won't be any exception, but the plot won't look right. 192 | 193 | To investigate, it would be helpful if we could inspect variables like ``x`` during execution of the function. 194 | 195 | To this end, we add a "break point" by inserting ``breakpoint()`` inside the function code block 196 | 197 | .. code-block:: python3 198 | :class: no-execute 199 | 200 | def plot_log(): 201 | breakpoint() 202 | fig, ax = plt.subplots() 203 | x = np.logspace(1, 2, 10) 204 | ax.plot(x, np.log(x)) 205 | plt.show() 206 | 207 | plot_log() 208 | 209 | Now let's run the script, and investigate via the debugger 210 | 211 | .. code-block:: ipython 212 | :class: no-execute 213 | 214 | > (6)plot_log() 215 | -> fig, ax = plt.subplots() 216 | (Pdb) n 217 | > (7)plot_log() 218 | -> x = np.logspace(1, 2, 10) 219 | (Pdb) n 220 | > (8)plot_log() 221 | -> ax.plot(x, np.log(x)) 222 | (Pdb) x 223 | array([ 10. , 12.91549665, 16.68100537, 21.5443469 , 224 | 27.82559402, 35.93813664, 46.41588834, 59.94842503, 225 | 77.42636827, 100. ]) 226 | 227 | We used ``n`` twice to step forward through the code (one line at a time). 228 | 229 | Then we printed the value of ``x`` to see what was happening with that variable. 230 | 231 | To exit from the debugger, use ``q``. 232 | 233 | 234 | 235 | Other Useful Magics 236 | ================================== 237 | 238 | In this lecture, we used the ``%debug`` IPython magic. 239 | 240 | There are many other useful magics: 241 | 242 | * ``%precision 4`` sets printed precision for floats to 4 decimal places 243 | 244 | * ``%whos`` gives a list of variables and their values 245 | 246 | * ``%quickref`` gives a list of magics 247 | 248 | The full list of magics is `here `_. 249 | -------------------------------------------------------------------------------- /source/rst/functions.rst: -------------------------------------------------------------------------------- 1 | .. _functions: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | .. highlight:: python3 6 | 7 | 8 | 9 | ********* 10 | Functions 11 | ********* 12 | 13 | 14 | 15 | .. index:: 16 | single: Python; User-defined functions 17 | 18 | .. contents:: :depth: 2 19 | 20 | 21 | 22 | Overview 23 | ======== 24 | 25 | One construct that's extremely useful and provided by almost all programming 26 | languages is **functions**. 27 | 28 | We have already met several functions, such as 29 | 30 | * the ``sqrt()`` function from NumPy and 31 | * the built-in ``print()`` function 32 | 33 | In this lecture we'll treat functions systematically and begin to learn just how 34 | useful and important they are. 35 | 36 | One of the things we will learn to do is build our own user-defined functions 37 | 38 | 39 | We will use the following imports. 40 | 41 | .. code-block:: ipython 42 | 43 | import numpy as np 44 | import matplotlib.pyplot as plt 45 | %matplotlib inline 46 | 47 | 48 | 49 | 50 | 51 | Function Basics 52 | ================== 53 | 54 | 55 | A function is a named section of a program that implements a specific task. 56 | 57 | Many functions exist already and we can use them off the shelf. 58 | 59 | First we review these functions and then discuss how we can build our own. 60 | 61 | 62 | Built-In Functions 63 | ------------------ 64 | 65 | Python has a number of *built-in* functions that are available without ``import``. 66 | 67 | 68 | We have already met some 69 | 70 | .. code-block:: python3 71 | 72 | max(19, 20) 73 | 74 | .. code-block:: python3 75 | 76 | print('foobar') 77 | 78 | .. code-block:: python3 79 | 80 | str(22) 81 | 82 | .. code-block:: python3 83 | 84 | type(22) 85 | 86 | 87 | Two more useful built-in functions are ``any()`` and ``all()`` 88 | 89 | .. code-block:: python3 90 | 91 | bools = False, True, True 92 | all(bools) # True if all are True and False otherwise 93 | 94 | .. code-block:: python3 95 | 96 | any(bools) # False if all are False and True otherwise 97 | 98 | 99 | The full list of Python built-ins is `here `_. 100 | 101 | 102 | Third Party Functions 103 | --------------------- 104 | 105 | If the built-in functions don't cover what we need, we either need to import 106 | functions or create our own. 107 | 108 | Examples of importing and using functions 109 | were given in the :doc:`previous lecture ` 110 | 111 | Here's another one, which tests whether a given year is a leap year: 112 | 113 | 114 | .. code-block:: python3 115 | 116 | import calendar 117 | 118 | calendar.isleap(2020) 119 | 120 | 121 | 122 | Defining Functions 123 | ================== 124 | 125 | In many instances, it is useful to be able to define our own functions. 126 | 127 | This will become clearer as you see more examples. 128 | 129 | Let's start by discussing how it's done. 130 | 131 | 132 | Syntax 133 | ------ 134 | 135 | Here's a very simple Python function, that implements the mathematical function 136 | :math:`f(x) = 2 x + 1` 137 | 138 | .. code-block:: python3 139 | 140 | def f(x): 141 | return 2 * x + 1 142 | 143 | Now that we've *defined* this function, let's *call* it and check whether it 144 | does what we expect: 145 | 146 | .. code-block:: python3 147 | 148 | f(1) 149 | 150 | .. code-block:: python3 151 | 152 | f(10) 153 | 154 | 155 | 156 | Here's a longer function, that computes the absolute value of a given number. 157 | 158 | (Such a function already exists as a built-in, but let's write our own for the 159 | exercise.) 160 | 161 | .. code-block:: python3 162 | 163 | def new_abs_function(x): 164 | 165 | if x < 0: 166 | abs_value = -x 167 | else: 168 | abs_value = x 169 | 170 | return abs_value 171 | 172 | Let's review the syntax here. 173 | 174 | * ``def`` is a Python keyword used to start function definitions. 175 | 176 | * ``def new_abs_function(x):`` indicates that the function is called ``new_abs_function`` and that it has a single argument ``x``. 177 | 178 | * The indented code is a code block called the *function body*. 179 | 180 | * The ``return`` keyword indicates that ``abs_value`` is the object that should be returned to the calling code. 181 | 182 | This whole function definition is read by the Python interpreter and stored in memory. 183 | 184 | Let's call it to check that it works: 185 | 186 | 187 | .. code-block:: python3 188 | 189 | print(new_abs_function(3)) 190 | print(new_abs_function(-3)) 191 | 192 | 193 | 194 | Why Write Functions? 195 | -------------------- 196 | 197 | User-defined functions are important for improving the clarity of your code by 198 | 199 | * separating different strands of logic 200 | 201 | * facilitating code reuse 202 | 203 | (Writing the same thing twice is `almost always a bad idea `_) 204 | 205 | We will say more about this :doc:`later `. 206 | 207 | 208 | Applications 209 | ============ 210 | 211 | 212 | Random Draws 213 | ------------ 214 | 215 | 216 | Consider again this code from the :doc:`previous lecture ` 217 | 218 | .. code-block:: python3 219 | 220 | ts_length = 100 221 | ϵ_values = [] # empty list 222 | 223 | for i in range(ts_length): 224 | e = np.random.randn() 225 | ϵ_values.append(e) 226 | 227 | plt.plot(ϵ_values) 228 | plt.show() 229 | 230 | 231 | We will break this program into two parts: 232 | 233 | #. A user-defined function that generates a list of random variables. 234 | 235 | #. The main part of the program that 236 | 237 | #. calls this function to get data 238 | 239 | #. plots the data 240 | 241 | This is accomplished in the next program 242 | 243 | .. _funcloopprog: 244 | 245 | .. code-block:: python3 246 | 247 | def generate_data(n): 248 | ϵ_values = [] 249 | for i in range(n): 250 | e = np.random.randn() 251 | ϵ_values.append(e) 252 | return ϵ_values 253 | 254 | data = generate_data(100) 255 | plt.plot(data) 256 | plt.show() 257 | 258 | 259 | When the interpreter gets to the expression ``generate_data(100)``, it executes the function body with ``n`` set equal to 100. 260 | 261 | The net result is that the name ``data`` is *bound* to the list ``ϵ_values`` returned by the function. 262 | 263 | 264 | 265 | Adding Conditions 266 | ----------------- 267 | 268 | .. index:: 269 | single: Python; Conditions 270 | 271 | Our function ``generate_data()`` is rather limited. 272 | 273 | Let's make it slightly more useful by giving it the ability to return either standard normals or uniform random variables on :math:`(0, 1)` as required. 274 | 275 | This is achieved in the next piece of code. 276 | 277 | 278 | .. _funcloopprog2: 279 | 280 | .. code-block:: python3 281 | 282 | 283 | def generate_data(n, generator_type): 284 | ϵ_values = [] 285 | for i in range(n): 286 | if generator_type == 'U': 287 | e = np.random.uniform(0, 1) 288 | else: 289 | e = np.random.randn() 290 | ϵ_values.append(e) 291 | return ϵ_values 292 | 293 | data = generate_data(100, 'U') 294 | plt.plot(data) 295 | plt.show() 296 | 297 | Hopefully, the syntax of the if/else clause is self-explanatory, with indentation again delimiting the extent of the code blocks. 298 | 299 | Notes 300 | 301 | * We are passing the argument ``U`` as a string, which is why we write it as ``'U'``. 302 | 303 | * Notice that equality is tested with the ``==`` syntax, not ``=``. 304 | 305 | * For example, the statement ``a = 10`` assigns the name ``a`` to the value ``10``. 306 | 307 | * The expression ``a == 10`` evaluates to either ``True`` or ``False``, depending on the value of ``a``. 308 | 309 | Now, there are several ways that we can simplify the code above. 310 | 311 | For example, we can get rid of the conditionals all together by just passing the desired generator type *as a function*. 312 | 313 | To understand this, consider the following version. 314 | 315 | .. _test_program_6: 316 | 317 | .. code-block:: python3 318 | 319 | 320 | def generate_data(n, generator_type): 321 | ϵ_values = [] 322 | for i in range(n): 323 | e = generator_type() 324 | ϵ_values.append(e) 325 | return ϵ_values 326 | 327 | data = generate_data(100, np.random.uniform) 328 | plt.plot(data) 329 | plt.show() 330 | 331 | 332 | Now, when we call the function ``generate_data()``, we pass ``np.random.uniform`` 333 | as the second argument. 334 | 335 | This object is a *function*. 336 | 337 | When the function call ``generate_data(100, np.random.uniform)`` is executed, Python runs the function code block with ``n`` equal to 100 and the name ``generator_type`` "bound" to the function ``np.random.uniform``. 338 | 339 | * While these lines are executed, the names ``generator_type`` and ``np.random.uniform`` are "synonyms", and can be used in identical ways. 340 | 341 | This principle works more generally---for example, consider the following piece of code 342 | 343 | .. code-block:: python3 344 | 345 | max(7, 2, 4) # max() is a built-in Python function 346 | 347 | .. code-block:: python3 348 | 349 | m = max 350 | m(7, 2, 4) 351 | 352 | Here we created another name for the built-in function ``max()``, which could 353 | then be used in identical ways. 354 | 355 | In the context of our program, the ability to bind new names to functions 356 | means that there is no problem *passing a function as an argument to another 357 | function*---as we did above. 358 | 359 | 360 | 361 | 362 | 363 | 364 | Exercises 365 | ========= 366 | 367 | 368 | 369 | Exercise 1 370 | ---------- 371 | 372 | Recall that :math:`n!` is read as ":math:`n` factorial" and defined as 373 | :math:`n! = n \times (n - 1) \times \cdots \times 2 \times 1`. 374 | 375 | There are functions to compute this in various modules, but let's 376 | write our own version as an exercise. 377 | 378 | In particular, write a function ``factorial`` such that ``factorial(n)`` returns :math:`n!` 379 | for any positive integer :math:`n`. 380 | 381 | 382 | 383 | Exercise 2 384 | ---------- 385 | 386 | The `binomial random variable `_ :math:`Y \sim Bin(n, p)` represents the number of successes in :math:`n` binary trials, where each trial succeeds with probability :math:`p`. 387 | 388 | Without any import besides ``from numpy.random import uniform``, write a function 389 | ``binomial_rv`` such that ``binomial_rv(n, p)`` generates one draw of :math:`Y`. 390 | 391 | Hint: If :math:`U` is uniform on :math:`(0, 1)` and :math:`p \in (0,1)`, then the expression ``U < p`` evaluates to ``True`` with probability :math:`p`. 392 | 393 | 394 | 395 | 396 | Exercise 3 397 | ---------- 398 | 399 | First, write a function that returns one realization of the following random device 400 | 401 | 1. Flip an unbiased coin 10 times. 402 | 2. If a head occurs ``k`` or more times consecutively within this sequence at least once, pay one dollar. 403 | 3. If not, pay nothing. 404 | 405 | Second, write another function that does the same task except that the second rule of the above random device becomes 406 | 407 | - If a head occurs ``k`` or more times within this sequence, pay one dollar. 408 | 409 | Use no import besides ``from numpy.random import uniform``. 410 | 411 | 412 | 413 | 414 | 415 | 416 | Solutions 417 | ========= 418 | 419 | 420 | Exercise 1 421 | ---------- 422 | 423 | Here's one solution. 424 | 425 | .. code-block:: python3 426 | 427 | def factorial(n): 428 | k = 1 429 | for i in range(n): 430 | k = k * (i + 1) 431 | return k 432 | 433 | factorial(4) 434 | 435 | 436 | 437 | Exercise 2 438 | ---------- 439 | 440 | .. code-block:: python3 441 | 442 | from numpy.random import uniform 443 | 444 | def binomial_rv(n, p): 445 | count = 0 446 | for i in range(n): 447 | U = uniform() 448 | if U < p: 449 | count = count + 1 # Or count += 1 450 | return count 451 | 452 | binomial_rv(10, 0.5) 453 | 454 | 455 | 456 | Exercise 3 457 | ---------- 458 | 459 | Here's a function for the first random device. 460 | 461 | .. code-block:: python3 462 | 463 | from numpy.random import uniform 464 | 465 | def draw(k): # pays if k consecutive successes in a sequence 466 | 467 | payoff = 0 468 | count = 0 469 | 470 | for i in range(10): 471 | U = uniform() 472 | count = count + 1 if U < 0.5 else 0 473 | print(count) # print counts for clarity 474 | if count == k: 475 | payoff = 1 476 | 477 | return payoff 478 | 479 | draw(3) 480 | 481 | Here's another function for the second random device. 482 | 483 | .. code-block:: python3 484 | 485 | def draw_new(k): # pays if k successes in a sequence 486 | 487 | payoff = 0 488 | count = 0 489 | 490 | for i in range(10): 491 | U = uniform() 492 | count = count + ( 1 if U < 0.5 else 0 ) 493 | print(count) 494 | if count == k: 495 | payoff = 1 496 | 497 | return payoff 498 | 499 | draw_new(3) 500 | 501 | 502 | -------------------------------------------------------------------------------- /source/rst/index.rst: -------------------------------------------------------------------------------- 1 | .. _index: 2 | 3 | ********************************************** 4 | Python Programming for Economics and Finance 5 | ********************************************** 6 | 7 | .. toctree:: 8 | :hidden: 9 | 10 | index_toc 11 | 12 | 13 | .. raw:: html 14 | 15 |
16 |

Python Programming for Economics and Finance

17 |
18 |
19 |
20 |

This website presents a set of lectures on Python programming for economics and finance, designed and written by Thomas J. Sargent and John Stachurski.

21 |

Last compiled:
22 | View source | 23 | View commits | See all contributors

24 |
25 | 32 |
33 | 37 |
38 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /source/rst/index_advanced_python_programming.rst: -------------------------------------------------------------------------------- 1 | .. include:: /_static/includes/header.raw 2 | 3 | ************************************ 4 | Advanced Python Programming 5 | ************************************ 6 | 7 | This part provides a look at more advanced concepts in Python programming 8 | 9 | .. only:: html 10 | 11 | Lectures 12 | ******** 13 | 14 | 15 | .. toctree:: 16 | :maxdepth: 2 17 | 18 | writing_good_code 19 | python_advanced_features 20 | debugging 21 | -------------------------------------------------------------------------------- /source/rst/index_learning_python.rst: -------------------------------------------------------------------------------- 1 | .. _learning_python: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | ********************** 6 | Introduction to Python 7 | ********************** 8 | 9 | This first part of the course provides a relatively fast-paced introduction to the Python programming language 10 | 11 | 12 | .. only:: html 13 | 14 | Lectures 15 | ******** 16 | 17 | 18 | .. toctree:: 19 | :maxdepth: 2 20 | 21 | about_py 22 | getting_started 23 | python_by_example 24 | functions 25 | python_essentials 26 | oop_intro 27 | python_oop 28 | -------------------------------------------------------------------------------- /source/rst/index_python_scientific_libraries.rst: -------------------------------------------------------------------------------- 1 | .. _learning_python: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | ********************************* 6 | The Scientific Libraries 7 | ********************************* 8 | 9 | Next we cover the third party libraries most useful for scientific work in Python 10 | 11 | 12 | .. only:: html 13 | 14 | Lectures 15 | ******** 16 | 17 | 18 | .. toctree:: 19 | :maxdepth: 2 20 | 21 | need_for_speed 22 | numpy 23 | matplotlib 24 | scipy 25 | numba 26 | parallelization 27 | pandas 28 | -------------------------------------------------------------------------------- /source/rst/index_toc.rst: -------------------------------------------------------------------------------- 1 | .. _toc: 2 | 3 | .. raw:: html 4 | 5 |

Powered by NumFOCUS logo

6 | 7 | .. only:: html 8 | 9 | Table of Contents 10 | ***************** 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | :titlesonly: 15 | 16 | about_lectures 17 | index_learning_python 18 | index_python_scientific_libraries 19 | index_advanced_python_programming 20 | 21 | 22 | .. toctree:: 23 | :hidden: 24 | 25 | 404 26 | search 27 | status 28 | troubleshooting 29 | 30 | | 31 | 32 | .. image:: http://assets.quantecon.org/img/banner.png 33 | :scale: 30% 34 | :align: center 35 | 36 | .. only:: latex 37 | 38 | Acknowledgements: These lectures have benefitted greatly from comments and 39 | suggestion from our colleagues, students and friends. Special thanks go to 40 | Anmol Bhandari, Long Bui, Jeong-Hun Choi, Chase Coleman, David Evans, Shunsuke Hori, 41 | Chenghan Hou, Doc-Jin Jang, Spencer Lyon, Qingyin Ma, Akira Matsushita, 42 | Matthew McKay, Tomohito Okabe, Alex Olssen, Nathan Palmer and Yixiao Zhou. 43 | -------------------------------------------------------------------------------- /source/rst/matplotlib.rst: -------------------------------------------------------------------------------- 1 | .. _matplotlib: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | ******************* 6 | :index:`Matplotlib` 7 | ******************* 8 | 9 | .. index:: 10 | single: Python; Matplotlib 11 | 12 | .. contents:: :depth: 2 13 | 14 | Overview 15 | ======== 16 | 17 | We've already generated quite a few figures in these lectures using `Matplotlib `__. 18 | 19 | Matplotlib is an outstanding graphics library, designed for scientific computing, with 20 | 21 | * high-quality 2D and 3D plots 22 | 23 | * output in all the usual formats (PDF, PNG, etc.) 24 | 25 | * LaTeX integration 26 | 27 | * fine-grained control over all aspects of presentation 28 | 29 | * animation, etc. 30 | 31 | 32 | 33 | Matplotlib's Split Personality 34 | ------------------------------ 35 | 36 | 37 | Matplotlib is unusual in that it offers two different interfaces to plotting. 38 | 39 | One is a simple MATLAB-style API (Application Programming Interface) that was written to help MATLAB refugees find a ready home. 40 | 41 | The other is a more "Pythonic" object-oriented API. 42 | 43 | For reasons described below, we recommend that you use the second API. 44 | 45 | But first, let's discuss the difference. 46 | 47 | 48 | 49 | 50 | The APIs 51 | ======== 52 | 53 | .. index:: 54 | single: Matplotlib; Simple API 55 | 56 | The MATLAB-style API 57 | -------------------- 58 | 59 | Here's the kind of easy example you might find in introductory treatments 60 | 61 | .. code-block:: ipython 62 | 63 | import matplotlib.pyplot as plt 64 | %matplotlib inline 65 | import numpy as np 66 | 67 | x = np.linspace(0, 10, 200) 68 | y = np.sin(x) 69 | 70 | plt.plot(x, y, 'b-', linewidth=2) 71 | plt.show() 72 | 73 | 74 | This is simple and convenient, but also somewhat limited and un-Pythonic. 75 | 76 | For example, in the function calls, a lot of objects get created and passed around without making themselves known to the programmer. 77 | 78 | Python programmers tend to prefer a more explicit style of programming (run ``import this`` in a code block and look at the second line). 79 | 80 | This leads us to the alternative, object-oriented Matplotlib API. 81 | 82 | The Object-Oriented API 83 | ----------------------- 84 | 85 | Here's the code corresponding to the preceding figure using the object-oriented API 86 | 87 | .. code-block:: python3 88 | 89 | fig, ax = plt.subplots() 90 | ax.plot(x, y, 'b-', linewidth=2) 91 | plt.show() 92 | 93 | 94 | Here the call ``fig, ax = plt.subplots()`` returns a pair, where 95 | 96 | * ``fig`` is a ``Figure`` instance---like a blank canvas. 97 | 98 | * ``ax`` is an ``AxesSubplot`` instance---think of a frame for plotting in. 99 | 100 | The ``plot()`` function is actually a method of ``ax``. 101 | 102 | While there's a bit more typing, the more explicit use of objects gives us better control. 103 | 104 | This will become more clear as we go along. 105 | 106 | 107 | Tweaks 108 | ------ 109 | 110 | Here we've changed the line to red and added a legend 111 | 112 | .. code-block:: python3 113 | 114 | fig, ax = plt.subplots() 115 | ax.plot(x, y, 'r-', linewidth=2, label='sine function', alpha=0.6) 116 | ax.legend() 117 | plt.show() 118 | 119 | We've also used ``alpha`` to make the line slightly transparent---which makes it look smoother. 120 | 121 | The location of the legend can be changed by replacing ``ax.legend()`` with ``ax.legend(loc='upper center')``. 122 | 123 | .. code-block:: python3 124 | 125 | fig, ax = plt.subplots() 126 | ax.plot(x, y, 'r-', linewidth=2, label='sine function', alpha=0.6) 127 | ax.legend(loc='upper center') 128 | plt.show() 129 | 130 | If everything is properly configured, then adding LaTeX is trivial 131 | 132 | .. code-block:: python3 133 | 134 | fig, ax = plt.subplots() 135 | ax.plot(x, y, 'r-', linewidth=2, label='$y=\sin(x)$', alpha=0.6) 136 | ax.legend(loc='upper center') 137 | plt.show() 138 | 139 | Controlling the ticks, adding titles and so on is also straightforward 140 | 141 | .. code-block:: python3 142 | 143 | fig, ax = plt.subplots() 144 | ax.plot(x, y, 'r-', linewidth=2, label='$y=\sin(x)$', alpha=0.6) 145 | ax.legend(loc='upper center') 146 | ax.set_yticks([-1, 0, 1]) 147 | ax.set_title('Test plot') 148 | plt.show() 149 | 150 | 151 | More Features 152 | ============= 153 | 154 | Matplotlib has a huge array of functions and features, which you can discover 155 | over time as you have need for them. 156 | 157 | We mention just a few. 158 | 159 | 160 | Multiple Plots on One Axis 161 | -------------------------- 162 | 163 | .. index:: 164 | single: Matplotlib; Multiple Plots on One Axis 165 | 166 | It's straightforward to generate multiple plots on the same axes. 167 | 168 | Here's an example that randomly generates three normal densities and adds a label with their mean 169 | 170 | .. code-block:: python3 171 | 172 | from scipy.stats import norm 173 | from random import uniform 174 | 175 | fig, ax = plt.subplots() 176 | x = np.linspace(-4, 4, 150) 177 | for i in range(3): 178 | m, s = uniform(-1, 1), uniform(1, 2) 179 | y = norm.pdf(x, loc=m, scale=s) 180 | current_label = f'$\mu = {m:.2}$' 181 | ax.plot(x, y, linewidth=2, alpha=0.6, label=current_label) 182 | ax.legend() 183 | plt.show() 184 | 185 | 186 | Multiple Subplots 187 | ----------------- 188 | 189 | .. index:: 190 | single: Matplotlib; Subplots 191 | 192 | Sometimes we want multiple subplots in one figure. 193 | 194 | Here's an example that generates 6 histograms 195 | 196 | .. code-block:: python3 197 | 198 | num_rows, num_cols = 3, 2 199 | fig, axes = plt.subplots(num_rows, num_cols, figsize=(10, 12)) 200 | for i in range(num_rows): 201 | for j in range(num_cols): 202 | m, s = uniform(-1, 1), uniform(1, 2) 203 | x = norm.rvs(loc=m, scale=s, size=100) 204 | axes[i, j].hist(x, alpha=0.6, bins=20) 205 | t = f'$\mu = {m:.2}, \quad \sigma = {s:.2}$' 206 | axes[i, j].set(title=t, xticks=[-4, 0, 4], yticks=[]) 207 | plt.show() 208 | 209 | 210 | 3D Plots 211 | -------- 212 | 213 | .. index:: 214 | single: Matplotlib; 3D Plots 215 | 216 | Matplotlib does a nice job of 3D plots --- here is one example 217 | 218 | 219 | .. code-block:: python3 220 | 221 | from mpl_toolkits.mplot3d.axes3d import Axes3D 222 | from matplotlib import cm 223 | 224 | 225 | def f(x, y): 226 | return np.cos(x**2 + y**2) / (1 + x**2 + y**2) 227 | 228 | xgrid = np.linspace(-3, 3, 50) 229 | ygrid = xgrid 230 | x, y = np.meshgrid(xgrid, ygrid) 231 | 232 | fig = plt.figure(figsize=(8, 6)) 233 | ax = fig.add_subplot(111, projection='3d') 234 | ax.plot_surface(x, 235 | y, 236 | f(x, y), 237 | rstride=2, cstride=2, 238 | cmap=cm.jet, 239 | alpha=0.7, 240 | linewidth=0.25) 241 | ax.set_zlim(-0.5, 1.0) 242 | plt.show() 243 | 244 | 245 | 246 | A Customizing Function 247 | ---------------------- 248 | 249 | Perhaps you will find a set of customizations that you regularly use. 250 | 251 | Suppose we usually prefer our axes to go through the origin, and to have a grid. 252 | 253 | Here's a nice example from `Matthew Doty `_ of how the object-oriented API can be used to build a custom ``subplots`` function that implements these changes. 254 | 255 | Read carefully through the code and see if you can follow what's going on 256 | 257 | .. code-block:: python3 258 | 259 | def subplots(): 260 | "Custom subplots with axes through the origin" 261 | fig, ax = plt.subplots() 262 | 263 | # Set the axes through the origin 264 | for spine in ['left', 'bottom']: 265 | ax.spines[spine].set_position('zero') 266 | for spine in ['right', 'top']: 267 | ax.spines[spine].set_color('none') 268 | 269 | ax.grid() 270 | return fig, ax 271 | 272 | 273 | fig, ax = subplots() # Call the local version, not plt.subplots() 274 | x = np.linspace(-2, 10, 200) 275 | y = np.sin(x) 276 | ax.plot(x, y, 'r-', linewidth=2, label='sine function', alpha=0.6) 277 | ax.legend(loc='lower right') 278 | plt.show() 279 | 280 | The custom ``subplots`` function 281 | 282 | #. calls the standard ``plt.subplots`` function internally to generate the ``fig, ax`` pair, 283 | 284 | #. makes the desired customizations to ``ax``, and 285 | 286 | #. passes the ``fig, ax`` pair back to the calling code. 287 | 288 | 289 | 290 | Further Reading 291 | =============== 292 | 293 | 294 | * The `Matplotlib gallery `__ provides many examples. 295 | 296 | * A nice `Matplotlib tutorial `__ by Nicolas Rougier, Mike Muller and Gael Varoquaux. 297 | 298 | * `mpltools `_ allows easy 299 | switching between plot styles. 300 | 301 | * `Seaborn `_ facilitates common statistics plots in Matplotlib. 302 | 303 | 304 | 305 | Exercises 306 | ========= 307 | 308 | 309 | Exercise 1 310 | ---------- 311 | 312 | 313 | Plot the function 314 | 315 | .. math:: 316 | 317 | f(x) = \cos(\pi \theta x) \exp(-x) 318 | 319 | over the interval :math:`[0, 5]` for each :math:`\theta` in ``np.linspace(0, 2, 10)``. 320 | 321 | Place all the curves in the same figure. 322 | 323 | The output should look like this 324 | 325 | 326 | .. figure:: /_static/lecture_specific/matplotlib/matplotlib_ex1.png 327 | 328 | 329 | 330 | 331 | Solutions 332 | ========= 333 | 334 | 335 | Exercise 1 336 | ---------- 337 | 338 | 339 | Here's one solution 340 | 341 | .. code:: ipython3 342 | 343 | def f(x, θ): 344 | return np.cos(np.pi * θ * x ) * np.exp(- x) 345 | 346 | θ_vals = np.linspace(0, 2, 10) 347 | x = np.linspace(0, 5, 200) 348 | fig, ax = plt.subplots() 349 | 350 | for θ in θ_vals: 351 | ax.plot(x, f(x, θ)) 352 | 353 | plt.show() 354 | -------------------------------------------------------------------------------- /source/rst/need_for_speed.rst: -------------------------------------------------------------------------------- 1 | .. _speed: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | ******************************* 6 | Python for Scientific Computing 7 | ******************************* 8 | 9 | .. contents:: :depth: 2 10 | 11 | .. epigraph:: 12 | 13 | "We should forget about small efficiencies, say about 97% of the time: 14 | premature optimization is the root of all evil." -- Donald Knuth 15 | 16 | 17 | 18 | Overview 19 | ======== 20 | 21 | Python is extremely popular for scientific computing, due to such factors as 22 | 23 | * the accessible and flexible nature of the language itself, 24 | 25 | * the huge range of high quality scientific libraries now available, 26 | 27 | * the fact that the language and libraries are open source, 28 | 29 | * the popular Anaconda Python distribution, which simplifies installation and 30 | management of those libraries, and 31 | 32 | * the recent surge of interest in using Python for machine learning and 33 | artificial intelligence. 34 | 35 | In this lecture we give a short overview of scientific computing in Python, 36 | addressing the following questions: 37 | 38 | * What are the relative strengths and weaknesses of Python for these tasks? 39 | 40 | * What are the main elements of the scientific Python ecosystem? 41 | 42 | * How is the situation changing over time? 43 | 44 | 45 | In addition to what's in Anaconda, this lecture will need 46 | 47 | .. code-block:: ipython 48 | :class: hide-output 49 | 50 | !conda install -y quantecon 51 | 52 | 53 | 54 | 55 | Scientific Libraries 56 | ============================= 57 | 58 | Let's briefly review Python's scientific libraries, starting with why we need 59 | them. 60 | 61 | The Role of Scientific Libraries 62 | -------------------------------- 63 | 64 | One obvious reason we use scientific libraries is because they implement 65 | routines we want to use. 66 | 67 | For example, it's almost always better to use an existing routine for root 68 | finding than to write a new one from scratch. 69 | 70 | (For standard algorithms, efficiency is maximized if the community can coordinate on a 71 | common set of implementations, written by experts and tuned by users to be as fast and robust as possible.) 72 | 73 | But this is not the only reason that we use Python's scientific libraries. 74 | 75 | Another is that pure Python, while flexible and elegant, is not fast. 76 | 77 | So we need libraries that are designed to accelerate execution of Python code. 78 | 79 | As we'll see below, there are now Python libraries that can do this extremely well. 80 | 81 | 82 | 83 | Python's Scientific Ecosystem 84 | ----------------------------- 85 | 86 | 87 | In terms of popularity, the big four in the world of scientific Python 88 | libraries are 89 | 90 | * NumPy 91 | * SciPy 92 | * Matplotlib 93 | * Pandas 94 | 95 | For us, there's another (relatively new) library that will also be essential for 96 | numerical computing: 97 | 98 | * Numba 99 | 100 | Over the next few lectures we'll see how to use these libraries. 101 | 102 | But first, let's quickly review how they fit together. 103 | 104 | * NumPy forms the foundations by providing a basic array data type (think of 105 | vectors and matrices) and functions for acting on these arrays (e.g., matrix 106 | multiplication). 107 | 108 | * SciPy builds on NumPy by adding the kinds of numerical methods that are 109 | routinely used in science (interpolation, optimization, root finding, etc.). 110 | 111 | * Matplotlib is used to generate figures, with a focus on plotting data stored in NumPy arrays. 112 | 113 | * Pandas provides types and functions for empirical work (e.g., manipulating data). 114 | 115 | * Numba accelerates execution via JIT compilation --- we'll learn about this 116 | soon. 117 | 118 | 119 | 120 | 121 | 122 | The Need for Speed 123 | ================== 124 | 125 | Now let's discuss execution speed. 126 | 127 | Higher-level languages like Python are optimized for humans. 128 | 129 | This means that the programmer can leave many details to the runtime environment 130 | 131 | * specifying variable types 132 | 133 | * memory allocation/deallocation, etc. 134 | 135 | The upside is that, compared to low-level languages, Python is typically faster to write, less error-prone and easier to debug. 136 | 137 | The downside is that Python is harder to optimize --- that is, turn into fast machine code --- than languages like C or Fortran. 138 | 139 | Indeed, the standard implementation of Python (called CPython) cannot match the speed of compiled languages such as C or Fortran. 140 | 141 | Does that mean that we should just switch to C or Fortran for everything? 142 | 143 | The answer is: No, no and one hundred times no! 144 | 145 | (This is what you should say to the senior professor insisting that the model 146 | needs to be rewritten in Fortran or C++.) 147 | 148 | There are two reasons why: 149 | 150 | First, for any given program, relatively few lines are ever going to 151 | be time-critical. 152 | 153 | Hence it is far more efficient to write most of our code in a high productivity language like Python. 154 | 155 | Second, even for those lines of code that *are* time-critical, we can now achieve the same speed as C or Fortran using Python's scientific libraries. 156 | 157 | 158 | Where are the Bottlenecks? 159 | -------------------------- 160 | 161 | Before we learn how to do this, let's try to understand why plain vanilla 162 | Python is slower than C or Fortran. 163 | 164 | This will, in turn, help us figure out how to speed things up. 165 | 166 | 167 | Dynamic Typing 168 | ^^^^^^^^^^^^^^ 169 | 170 | .. index:: 171 | single: Dynamic Typing 172 | 173 | Consider this Python operation 174 | 175 | .. code-block:: python3 176 | 177 | a, b = 10, 10 178 | a + b 179 | 180 | 181 | Even for this simple operation, the Python interpreter has a fair bit of work to do. 182 | 183 | For example, in the statement ``a + b``, the interpreter has to know which 184 | operation to invoke. 185 | 186 | If ``a`` and ``b`` are strings, then ``a + b`` requires string concatenation 187 | 188 | .. code-block:: python3 189 | 190 | a, b = 'foo', 'bar' 191 | a + b 192 | 193 | 194 | If ``a`` and ``b`` are lists, then ``a + b`` requires list concatenation 195 | 196 | .. code-block:: python3 197 | 198 | a, b = ['foo'], ['bar'] 199 | a + b 200 | 201 | 202 | (We say that the operator ``+`` is *overloaded* --- its action depends on the 203 | type of the objects on which it acts) 204 | 205 | As a result, Python must check the type of the objects and then call the correct operation. 206 | 207 | This involves substantial overheads. 208 | 209 | Static Types 210 | ^^^^^^^^^^^^ 211 | 212 | .. index:: 213 | single: Static Types 214 | 215 | Compiled languages avoid these overheads with explicit, static types. 216 | 217 | For example, consider the following C code, which sums the integers from 1 to 10 218 | 219 | .. code-block:: c 220 | :class: no-execute 221 | 222 | #include 223 | 224 | int main(void) { 225 | int i; 226 | int sum = 0; 227 | for (i = 1; i <= 10; i++) { 228 | sum = sum + i; 229 | } 230 | printf("sum = %d\n", sum); 231 | return 0; 232 | } 233 | 234 | The variables ``i`` and ``sum`` are explicitly declared to be integers. 235 | 236 | Hence, the meaning of addition here is completely unambiguous. 237 | 238 | Data Access 239 | ----------- 240 | 241 | Another drag on speed for high-level languages is data access. 242 | 243 | To illustrate, let's consider the problem of summing some data --- say, a collection of integers. 244 | 245 | Summing with Compiled Code 246 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 247 | 248 | In C or Fortran, these integers would typically be stored in an array, which 249 | is a simple data structure for storing homogeneous data. 250 | 251 | Such an array is stored in a single contiguous block of memory 252 | 253 | * In modern computers, memory addresses are allocated to each byte (one byte = 8 bits). 254 | 255 | * For example, a 64 bit integer is stored in 8 bytes of memory. 256 | 257 | * An array of :math:`n` such integers occupies :math:`8n` **consecutive** memory slots. 258 | 259 | Moreover, the compiler is made aware of the data type by the programmer. 260 | 261 | * In this case 64 bit integers 262 | 263 | Hence, each successive data point can be accessed by shifting forward in memory 264 | space by a known and fixed amount. 265 | 266 | * In this case 8 bytes 267 | 268 | 269 | Summing in Pure Python 270 | ^^^^^^^^^^^^^^^^^^^^^^ 271 | 272 | Python tries to replicate these ideas to some degree. 273 | 274 | For example, in the standard Python implementation (CPython), list elements are placed in memory locations that are in a sense contiguous. 275 | 276 | However, these list elements are more like pointers to data rather than actual data. 277 | 278 | Hence, there is still overhead involved in accessing the data values themselves. 279 | 280 | This is a considerable drag on speed. 281 | 282 | In fact, it's generally true that memory traffic is a major culprit when it comes to slow execution. 283 | 284 | Let's look at some ways around these problems. 285 | 286 | 287 | 288 | :index:`Vectorization` 289 | ====================== 290 | 291 | .. index:: 292 | single: Python; Vectorization 293 | 294 | There is a clever method called **vectorization** that can be 295 | used to speed up high level languages in numerical applications. 296 | 297 | The key idea is to send array processing operations in batch to pre-compiled 298 | and efficient native machine code. 299 | 300 | The machine code itself is typically compiled from carefully optimized C or Fortran. 301 | 302 | For example, when working in a high level language, the operation of inverting a large matrix can be subcontracted to efficient machine code that is pre-compiled for this purpose and supplied to users as part of a package. 303 | 304 | This clever idea dates back to MATLAB, which uses vectorization extensively. 305 | 306 | Vectorization can greatly accelerate many numerical computations (but not all, 307 | as we shall see). 308 | 309 | Let's see how vectorization works in Python, using NumPy. 310 | 311 | 312 | Operations on Arrays 313 | -------------------- 314 | 315 | .. index:: 316 | single: Vectorization; Operations on Arrays 317 | 318 | First, let's run some imports 319 | 320 | .. code-block:: python3 321 | 322 | import random 323 | import numpy as np 324 | import quantecon as qe 325 | 326 | Next let's try some non-vectorized code, which uses a native Python loop to generate, 327 | square and then sum a large number of random variables: 328 | 329 | .. code-block:: python3 330 | 331 | n = 1_000_000 332 | 333 | .. code-block:: python3 334 | 335 | %%time 336 | 337 | y = 0 # Will accumulate and store sum 338 | for i in range(n): 339 | x = random.uniform(0, 1) 340 | y += x**2 341 | 342 | The following vectorized code achieves the same thing. 343 | 344 | .. code-block:: ipython 345 | 346 | %%time 347 | 348 | x = np.random.uniform(0, 1, n) 349 | y = np.sum(x**2) 350 | 351 | 352 | As you can see, the second code block runs much faster. Why? 353 | 354 | The second code block breaks the loop down into three basic operations 355 | 356 | #. draw ``n`` uniforms 357 | 358 | #. square them 359 | 360 | #. sum them 361 | 362 | These are sent as batch operators to optimized machine code. 363 | 364 | Apart from minor overheads associated with sending data back and forth, the result is C or Fortran-like speed. 365 | 366 | When we run batch operations on arrays like this, we say that the code is *vectorized*. 367 | 368 | Vectorized code is typically fast and efficient. 369 | 370 | It is also surprisingly flexible, in the sense that many operations can be vectorized. 371 | 372 | The next section illustrates this point. 373 | 374 | 375 | 376 | 377 | 378 | .. _ufuncs: 379 | 380 | 381 | Universal Functions 382 | ------------------- 383 | 384 | .. index:: 385 | single: NumPy; Universal Functions 386 | 387 | Many functions provided by NumPy are so-called *universal functions* --- also called `ufuncs `__. 388 | 389 | This means that they 390 | 391 | * map scalars into scalars, as expected 392 | 393 | * map arrays into arrays, acting element-wise 394 | 395 | For example, ``np.cos`` is a ufunc: 396 | 397 | .. code-block:: python3 398 | 399 | np.cos(1.0) 400 | 401 | .. code-block:: python3 402 | 403 | np.cos(np.linspace(0, 1, 3)) 404 | 405 | 406 | By exploiting ufuncs, many operations can be vectorized. 407 | 408 | For example, consider the problem of maximizing a function :math:`f` of two 409 | variables :math:`(x,y)` over the square :math:`[-a, a] \times [-a, a]`. 410 | 411 | For :math:`f` and :math:`a` let's choose 412 | 413 | .. math:: 414 | 415 | f(x,y) = \frac{\cos(x^2 + y^2)}{1 + x^2 + y^2} 416 | \quad \text{and} \quad 417 | a = 3 418 | 419 | 420 | Here's a plot of :math:`f` 421 | 422 | .. code-block:: ipython 423 | 424 | import matplotlib.pyplot as plt 425 | %matplotlib inline 426 | from mpl_toolkits.mplot3d.axes3d import Axes3D 427 | from matplotlib import cm 428 | 429 | def f(x, y): 430 | return np.cos(x**2 + y**2) / (1 + x**2 + y**2) 431 | 432 | xgrid = np.linspace(-3, 3, 50) 433 | ygrid = xgrid 434 | x, y = np.meshgrid(xgrid, ygrid) 435 | 436 | fig = plt.figure(figsize=(8, 6)) 437 | ax = fig.add_subplot(111, projection='3d') 438 | ax.plot_surface(x, 439 | y, 440 | f(x, y), 441 | rstride=2, cstride=2, 442 | cmap=cm.jet, 443 | alpha=0.7, 444 | linewidth=0.25) 445 | ax.set_zlim(-0.5, 1.0) 446 | ax.set_xlabel('$x$', fontsize=14) 447 | ax.set_ylabel('$y$', fontsize=14) 448 | plt.show() 449 | 450 | To maximize it, we're going to use a naive grid search: 451 | 452 | #. Evaluate :math:`f` for all :math:`(x,y)` in a grid on the square. 453 | 454 | #. Return the maximum of observed values. 455 | 456 | The grid will be 457 | 458 | .. code-block:: python3 459 | 460 | grid = np.linspace(-3, 3, 1000) 461 | 462 | Here's a non-vectorized version that uses Python loops. 463 | 464 | .. code-block:: python3 465 | 466 | %%time 467 | 468 | m = -np.inf 469 | 470 | for x in grid: 471 | for y in grid: 472 | z = f(x, y) 473 | if z > m: 474 | m = z 475 | 476 | 477 | And here's a vectorized version 478 | 479 | .. code-block:: python3 480 | 481 | %%time 482 | 483 | x, y = np.meshgrid(grid, grid) 484 | np.max(f(x, y)) 485 | 486 | 487 | In the vectorized version, all the looping takes place in compiled code. 488 | 489 | As you can see, the second version is **much** faster. 490 | 491 | (We'll make it even faster again later on, using more scientific programming tricks.) 492 | 493 | 494 | 495 | .. _numba-p_c_vectorization: 496 | 497 | Beyond Vectorization 498 | ==================== 499 | 500 | 501 | At its best, vectorization yields fast, simple code. 502 | 503 | However, it's not without disadvantages. 504 | 505 | One issue is that it can be highly memory-intensive. 506 | 507 | For example, the vectorized maximization routine above is far more memory 508 | intensive than the non-vectorized version that preceded it. 509 | 510 | This is because vectorization tends to create many intermediate arrays before 511 | producing the final calculation. 512 | 513 | Another issue is that not all algorithms can be vectorized. 514 | 515 | In these kinds of settings, we need to go back to loops. 516 | 517 | Fortunately, there are alternative ways to speed up Python loops that work in 518 | almost any setting. 519 | 520 | For example, in the last few years, a new Python library called `Numba 521 | `__ has appeared that solves the main problems 522 | with vectorization listed above. 523 | 524 | It does so through something called **just in time (JIT) compilation**, 525 | which can generate extremely fast and efficient code. 526 | 527 | We'll learn how to use Numba :doc:`soon `. 528 | -------------------------------------------------------------------------------- /source/rst/oop_intro.rst: -------------------------------------------------------------------------------- 1 | .. _oop_intro: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | ************************************************** 6 | OOP I: Introduction to Object Oriented Programming 7 | ************************************************** 8 | 9 | .. contents:: :depth: 2 10 | 11 | Overview 12 | ============ 13 | 14 | 15 | `OOP `_ is one of the major paradigms in programming. 16 | 17 | 18 | The traditional programming paradigm (think Fortran, C, MATLAB, etc.) is called *procedural*. 19 | 20 | It works as follows 21 | 22 | * The program has a state corresponding to the values of its variables. 23 | 24 | * Functions are called to act on these data. 25 | 26 | * Data are passed back and forth via function calls. 27 | 28 | 29 | In contrast, in the OOP paradigm 30 | 31 | * data and functions are "bundled together" into "objects" 32 | 33 | (Functions in this context are referred to as **methods**) 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | Python and OOP 42 | -------------- 43 | 44 | Python is a pragmatic language that blends object-oriented and procedural styles, rather than taking a purist approach. 45 | 46 | However, at a foundational level, Python *is* object-oriented. 47 | 48 | In particular, in Python, *everything is an object*. 49 | 50 | In this lecture, we explain what that statement means and why it matters. 51 | 52 | 53 | 54 | 55 | 56 | Objects 57 | ======= 58 | 59 | .. index:: 60 | single: Python; Objects 61 | 62 | 63 | In Python, an *object* is a collection of data and instructions held in computer memory that consists of 64 | 65 | #. a type 66 | 67 | #. a unique identity 68 | 69 | #. data (i.e., content) 70 | 71 | #. methods 72 | 73 | These concepts are defined and discussed sequentially below. 74 | 75 | 76 | 77 | 78 | 79 | 80 | .. _type: 81 | 82 | Type 83 | ---- 84 | 85 | .. index:: 86 | single: Python; Type 87 | 88 | Python provides for different types of objects, to accommodate different categories of data. 89 | 90 | For example 91 | 92 | .. code-block:: python3 93 | 94 | s = 'This is a string' 95 | type(s) 96 | 97 | .. code-block:: python3 98 | 99 | x = 42 # Now let's create an integer 100 | type(x) 101 | 102 | The type of an object matters for many expressions. 103 | 104 | For example, the addition operator between two strings means concatenation 105 | 106 | .. code-block:: python3 107 | 108 | '300' + 'cc' 109 | 110 | On the other hand, between two numbers it means ordinary addition 111 | 112 | .. code-block:: python3 113 | 114 | 300 + 400 115 | 116 | Consider the following expression 117 | 118 | .. code-block:: python3 119 | :class: skip-test 120 | 121 | '300' + 400 122 | 123 | 124 | Here we are mixing types, and it's unclear to Python whether the user wants to 125 | 126 | * convert ``'300'`` to an integer and then add it to ``400``, or 127 | 128 | * convert ``400`` to string and then concatenate it with ``'300'`` 129 | 130 | Some languages might try to guess but Python is *strongly typed* 131 | 132 | * Type is important, and implicit type conversion is rare. 133 | 134 | * Python will respond instead by raising a ``TypeError``. 135 | 136 | 137 | To avoid the error, you need to clarify by changing the relevant type. 138 | 139 | For example, 140 | 141 | .. code-block:: python3 142 | 143 | int('300') + 400 # To add as numbers, change the string to an integer 144 | 145 | 146 | 147 | .. _identity: 148 | 149 | Identity 150 | -------- 151 | 152 | .. index:: 153 | single: Python; Identity 154 | 155 | In Python, each object has a unique identifier, which helps Python (and us) keep track of the object. 156 | 157 | The identity of an object can be obtained via the ``id()`` function 158 | 159 | .. code-block:: python3 160 | 161 | y = 2.5 162 | z = 2.5 163 | id(y) 164 | 165 | .. code-block:: python3 166 | 167 | id(z) 168 | 169 | In this example, ``y`` and ``z`` happen to have the same value (i.e., ``2.5``), but they are not the same object. 170 | 171 | The identity of an object is in fact just the address of the object in memory. 172 | 173 | 174 | 175 | 176 | 177 | Object Content: Data and Attributes 178 | ----------------------------------- 179 | 180 | .. index:: 181 | single: Python; Content 182 | 183 | If we set ``x = 42`` then we create an object of type ``int`` that contains 184 | the data ``42``. 185 | 186 | In fact, it contains more, as the following example shows 187 | 188 | 189 | .. code-block:: python3 190 | 191 | x = 42 192 | x 193 | 194 | .. code-block:: python3 195 | 196 | x.imag 197 | 198 | .. code-block:: python3 199 | 200 | x.__class__ 201 | 202 | When Python creates this integer object, it stores with it various auxiliary information, such as the imaginary part, and the type. 203 | 204 | Any name following a dot is called an *attribute* of the object to the left of the dot. 205 | 206 | * e.g.,``imag`` and ``__class__`` are attributes of ``x``. 207 | 208 | 209 | We see from this example that objects have attributes that contain auxiliary information. 210 | 211 | 212 | They also have attributes that act like functions, called *methods*. 213 | 214 | These attributes are important, so let's discuss them in-depth. 215 | 216 | 217 | .. _methods: 218 | 219 | Methods 220 | ------- 221 | 222 | .. index:: 223 | single: Python; Methods 224 | 225 | Methods are *functions that are bundled with objects*. 226 | 227 | 228 | 229 | Formally, methods are attributes of objects that are callable (i.e., can be called as functions) 230 | 231 | .. code-block:: python3 232 | 233 | x = ['foo', 'bar'] 234 | callable(x.append) 235 | 236 | .. code-block:: python3 237 | 238 | callable(x.__doc__) 239 | 240 | 241 | 242 | Methods typically act on the data contained in the object they belong to, or combine that data with other data 243 | 244 | .. code-block:: python3 245 | 246 | x = ['a', 'b'] 247 | x.append('c') 248 | s = 'This is a string' 249 | s.upper() 250 | 251 | .. code-block:: python3 252 | 253 | s.lower() 254 | 255 | .. code-block:: python3 256 | 257 | s.replace('This', 'That') 258 | 259 | A great deal of Python functionality is organized around method calls. 260 | 261 | For example, consider the following piece of code 262 | 263 | .. code-block:: python3 264 | 265 | x = ['a', 'b'] 266 | x[0] = 'aa' # Item assignment using square bracket notation 267 | x 268 | 269 | It doesn't look like there are any methods used here, but in fact the square bracket assignment notation is just a convenient interface to a method call. 270 | 271 | What actually happens is that Python calls the ``__setitem__`` method, as follows 272 | 273 | .. code-block:: python3 274 | 275 | x = ['a', 'b'] 276 | x.__setitem__(0, 'aa') # Equivalent to x[0] = 'aa' 277 | x 278 | 279 | (If you wanted to you could modify the ``__setitem__`` method, so that square bracket assignment does something totally different) 280 | 281 | 282 | 283 | 284 | Summary 285 | ========== 286 | 287 | In Python, *everything in memory is treated as an object*. 288 | 289 | This includes not just lists, strings, etc., but also less obvious things, such as 290 | 291 | * functions (once they have been read into memory) 292 | 293 | * modules (ditto) 294 | 295 | * files opened for reading or writing 296 | 297 | * integers, etc. 298 | 299 | Consider, for example, functions. 300 | 301 | When Python reads a function definition, it creates a **function object** and stores it in memory. 302 | 303 | 304 | The following code illustrates 305 | 306 | .. code-block:: python3 307 | 308 | def f(x): return x**2 309 | f 310 | 311 | 312 | .. code-block:: python3 313 | 314 | type(f) 315 | 316 | .. code-block:: python3 317 | 318 | id(f) 319 | 320 | .. code-block:: python3 321 | 322 | f.__name__ 323 | 324 | We can see that ``f`` has type, identity, attributes and so on---just like any other object. 325 | 326 | It also has methods. 327 | 328 | One example is the ``__call__`` method, which just evaluates the function 329 | 330 | .. code-block:: python3 331 | 332 | f.__call__(3) 333 | 334 | Another is the ``__dir__`` method, which returns a list of attributes. 335 | 336 | 337 | Modules loaded into memory are also treated as objects 338 | 339 | .. code-block:: python3 340 | 341 | import math 342 | 343 | id(math) 344 | 345 | 346 | This uniform treatment of data in Python (everything is an object) helps keep the language simple and consistent. 347 | -------------------------------------------------------------------------------- /source/rst/parallelization.rst: -------------------------------------------------------------------------------- 1 | .. _parallel: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | *************** 6 | Parallelization 7 | *************** 8 | 9 | .. contents:: :depth: 2 10 | 11 | In addition to what's in Anaconda, this lecture will need the following libraries: 12 | 13 | .. code-block:: ipython 14 | :class: hide-output 15 | 16 | !conda install -y quantecon 17 | 18 | 19 | Overview 20 | ======== 21 | 22 | 23 | The growth of CPU clock speed (i.e., the speed at which a single chain of logic can 24 | be run) has slowed dramatically in recent years. 25 | 26 | This is unlikely to change in the near future, due to inherent physical 27 | limitations on the construction of chips and circuit boards. 28 | 29 | Chip designers and computer programmers have responded to the slowdown by 30 | seeking a different path to fast execution: parallelization. 31 | 32 | Hardware makers have increased the number of cores (physical CPUs) embedded in each machine. 33 | 34 | For programmers, the challenge has been to exploit these multiple CPUs by running many processes in parallel (i.e., simultaneously). 35 | 36 | This is particularly important in scientific programming, which requires handling 37 | 38 | * large amounts of data and 39 | 40 | * CPU intensive simulations and other calculations. 41 | 42 | In this lecture we discuss parallelization for scientific computing, with a focus on 43 | 44 | #. the best tools for parallelization in Python and 45 | 46 | #. how these tools can be applied to quantitative economic problems. 47 | 48 | 49 | Let's start with some imports: 50 | 51 | .. code-block:: ipython 52 | 53 | import numpy as np 54 | import quantecon as qe 55 | import matplotlib.pyplot as plt 56 | 57 | %matplotlib inline 58 | 59 | 60 | Types of Parallelization 61 | ======================== 62 | 63 | Large textbooks have been written on different approaches to parallelization but we will keep a tight focus on what's most useful to us. 64 | 65 | We will briefly review the two main kinds of parallelization commonly used in 66 | scientific computing and discuss their pros and cons. 67 | 68 | 69 | Multiprocessing 70 | --------------- 71 | 72 | Multiprocessing means concurrent execution of multiple processes using more than one processor. 73 | 74 | In this context, a **process** is a chain of instructions (i.e., a program). 75 | 76 | Multiprocessing can be carried out on one machine with multiple CPUs or on a 77 | collection of machines connected by a network. 78 | 79 | In the latter case, the collection of machines is usually called a 80 | **cluster**. 81 | 82 | With multiprocessing, each process has its own memory space, although the 83 | physical memory chip might be shared. 84 | 85 | 86 | Multithreading 87 | -------------- 88 | 89 | Multithreading is similar to multiprocessing, except that, during execution, the threads all share the same memory space. 90 | 91 | Native Python struggles to implement multithreading due to some `legacy design 92 | features `__. 93 | 94 | But this is not a restriction for scientific libraries like NumPy and Numba. 95 | 96 | Functions imported from these libraries and JIT-compiled code run in low level 97 | execution environments where Python's legacy restrictions don't apply. 98 | 99 | 100 | Advantages and Disadvantages 101 | ---------------------------- 102 | 103 | Multithreading is more lightweight because most system and memory resources 104 | are shared by the threads. 105 | 106 | In addition, the fact that multiple threads all access a shared pool of memory 107 | is extremely convenient for numerical programming. 108 | 109 | On the other hand, multiprocessing is more flexible and can be distributed 110 | across clusters. 111 | 112 | For the great majority of what we do in these lectures, multithreading will 113 | suffice. 114 | 115 | 116 | Implicit Multithreading in NumPy 117 | ================================ 118 | 119 | Actually, you have already been using multithreading in your Python code, 120 | although you might not have realized it. 121 | 122 | (We are, as usual, assuming that you are running the latest version of 123 | Anaconda Python.) 124 | 125 | This is because NumPy cleverly implements multithreading in a lot of its 126 | compiled code. 127 | 128 | Let's look at some examples to see this in action. 129 | 130 | A Matrix Operation 131 | ------------------ 132 | 133 | The next piece of code computes the eigenvalues of a large number of randomly 134 | generated matrices. 135 | 136 | It takes a few seconds to run. 137 | 138 | .. code-block:: python3 139 | 140 | n = 20 141 | m = 1000 142 | for i in range(n): 143 | X = np.random.randn(m, m) 144 | λ = np.linalg.eigvals(X) 145 | 146 | Now, let's look at the output of the `htop` system monitor on our machine while 147 | this code is running: 148 | 149 | .. figure:: /_static/lecture_specific/parallelization/htop_parallel_npmat.png 150 | :scale: 45% 151 | 152 | We can see that 4 of the 8 CPUs are running at full speed. 153 | 154 | 155 | This is because NumPy's ``eigvals`` routine neatly splits up the tasks and 156 | distributes them to different threads. 157 | 158 | 159 | A Multithreaded Ufunc 160 | --------------------- 161 | 162 | Over the last few years, NumPy has managed to push this kind of multithreading 163 | out to more and more operations. 164 | 165 | For example, let's return to a maximization problem :ref:`discussed previously `: 166 | 167 | .. code-block:: python3 168 | 169 | def f(x, y): 170 | return np.cos(x**2 + y**2) / (1 + x**2 + y**2) 171 | 172 | grid = np.linspace(-3, 3, 5000) 173 | x, y = np.meshgrid(grid, grid) 174 | 175 | .. code-block:: ipython3 176 | 177 | %timeit np.max(f(x, y)) 178 | 179 | If you have a system monitor such as `htop` (Linux/Mac) or `perfmon` 180 | (Windows), then try running this and then observing the load on your CPUs. 181 | 182 | (You will probably need to bump up the grid size to see large effects.) 183 | 184 | At least on our machine, the output shows that the operation is successfully 185 | distributed across multiple threads. 186 | 187 | This is one of the reasons why the vectorized code above is fast. 188 | 189 | A Comparison with Numba 190 | ----------------------- 191 | 192 | To get some basis for comparison for the last example, let's try the same 193 | thing with Numba. 194 | 195 | In fact there is an easy way to do this, since Numba can also be used to 196 | create custom :ref:`ufuncs ` with the `@vectorize 197 | `__ decorator. 198 | 199 | .. code-block:: python3 200 | 201 | from numba import vectorize 202 | 203 | @vectorize 204 | def f_vec(x, y): 205 | return np.cos(x**2 + y**2) / (1 + x**2 + y**2) 206 | 207 | np.max(f_vec(x, y)) # Run once to compile 208 | 209 | .. code-block:: ipython3 210 | 211 | %timeit np.max(f_vec(x, y)) 212 | 213 | At least on our machine, the difference in the speed between the 214 | Numba version and the vectorized NumPy version shown above is not large. 215 | 216 | But there's quite a bit going on here so let's try to break down what is 217 | happening. 218 | 219 | Both Numba and NumPy use efficient machine code that's specialized to these 220 | floating point operations. 221 | 222 | However, the code NumPy uses is, in some ways, less efficient. 223 | 224 | The reason is that, in NumPy, the operation ``np.cos(x**2 + y**2) / (1 + 225 | x**2 + y**2)`` generates several intermediate arrays. 226 | 227 | For example, a new array is created when ``x**2`` is calculated. 228 | 229 | The same is true when ``y**2`` is calculated, and then ``x**2 + y**2`` and so on. 230 | 231 | Numba avoids creating all these intermediate arrays by compiling one 232 | function that is specialized to the entire operation. 233 | 234 | But if this is true, then why isn't the Numba code faster? 235 | 236 | The reason is that NumPy makes up for its disadvantages with implicit 237 | multithreading, as we've just discussed. 238 | 239 | Multithreading a Numba Ufunc 240 | ---------------------------- 241 | 242 | Can we get both of these advantages at once? 243 | 244 | In other words, can we pair 245 | 246 | * the efficiency of Numba's highly specialized JIT compiled function and 247 | 248 | * the speed gains from parallelization obtained by NumPy's implicit 249 | multithreading? 250 | 251 | It turns out that we can, by adding some type information plus ``target='parallel'``. 252 | 253 | .. code-block:: python3 254 | 255 | @vectorize('float64(float64, float64)', target='parallel') 256 | def f_vec(x, y): 257 | return np.cos(x**2 + y**2) / (1 + x**2 + y**2) 258 | 259 | np.max(f_vec(x, y)) # Run once to compile 260 | 261 | .. code-block:: ipython3 262 | 263 | %timeit np.max(f_vec(x, y)) 264 | 265 | Now our code runs significantly faster than the NumPy version. 266 | 267 | 268 | 269 | Multithreaded Loops in Numba 270 | ============================ 271 | 272 | We just saw one approach to parallelization in Numba, using the ``parallel`` 273 | flag in ``@vectorize``. 274 | 275 | This is neat but, it turns out, not well suited to many problems we consider. 276 | 277 | Fortunately, Numba provides another approach to multithreading that will work 278 | for us almost everywhere parallelization is possible. 279 | 280 | To illustrate, let's look first at a simple, single-threaded (i.e., non-parallelized) piece of code. 281 | 282 | The code simulates updating the wealth :math:`w_t` of a household via the rule 283 | 284 | .. math:: 285 | 286 | w_{t+1} = R_{t+1} s w_t + y_{t+1} 287 | 288 | Here 289 | 290 | * :math:`R` is the gross rate of return on assets 291 | * :math:`s` is the savings rate of the household and 292 | * :math:`y` is labor income. 293 | 294 | We model both :math:`R` and :math:`y` as independent draws from a lognormal 295 | distribution. 296 | 297 | Here's the code: 298 | 299 | .. code-block:: ipython 300 | 301 | from numpy.random import randn 302 | from numba import njit 303 | 304 | @njit 305 | def h(w, r=0.1, s=0.3, v1=0.1, v2=1.0): 306 | """ 307 | Updates household wealth. 308 | """ 309 | 310 | # Draw shocks 311 | R = np.exp(v1 * randn()) * (1 + r) 312 | y = np.exp(v2 * randn()) 313 | 314 | # Update wealth 315 | w = R * s * w + y 316 | return w 317 | 318 | 319 | Let's have a look at how wealth evolves under this rule. 320 | 321 | .. code-block:: ipython 322 | 323 | fig, ax = plt.subplots() 324 | 325 | T = 100 326 | w = np.empty(T) 327 | w[0] = 5 328 | for t in range(T-1): 329 | w[t+1] = h(w[t]) 330 | 331 | ax.plot(w) 332 | ax.set_xlabel('$t$', fontsize=12) 333 | ax.set_ylabel('$w_{t}$', fontsize=12) 334 | plt.show() 335 | 336 | Now let's suppose that we have a large population of households and we want to 337 | know what median wealth will be. 338 | 339 | This is not easy to solve with pencil and paper, so we will use simulation 340 | instead. 341 | 342 | In particular, we will simulate a large number of households and then 343 | calculate median wealth for this group. 344 | 345 | Suppose we are interested in the long-run average of this median over time. 346 | 347 | It turns out that, for the specification that we've chosen above, we can 348 | calculate this by taking a one-period snapshot of what has happened to median 349 | wealth of the group at the end of a long simulation. 350 | 351 | Moreover, provided the simulation period is long enough, initial conditions 352 | don't matter. 353 | 354 | * This is due to something called ergodicity, which we will discuss `later on `_. 355 | 356 | So, in summary, we are going to simulate 50,000 households by 357 | 358 | #. arbitrarily setting initial wealth to 1 and 359 | 360 | #. simulating forward in time for 1,000 periods. 361 | 362 | Then we'll calculate median wealth at the end period. 363 | 364 | Here's the code: 365 | 366 | .. code-block:: ipython 367 | 368 | @njit 369 | def compute_long_run_median(w0=1, T=1000, num_reps=50_000): 370 | 371 | obs = np.empty(num_reps) 372 | for i in range(num_reps): 373 | w = w0 374 | for t in range(T): 375 | w = h(w) 376 | obs[i] = w 377 | 378 | return np.median(obs) 379 | 380 | Let's see how fast this runs: 381 | 382 | .. code-block:: ipython 383 | 384 | %%time 385 | compute_long_run_median() 386 | 387 | 388 | To speed this up, we're going to parallelize it via multithreading. 389 | 390 | To do so, we add the ``parallel=True`` flag and change ``range`` to ``prange``: 391 | 392 | .. code-block:: ipython 393 | 394 | from numba import prange 395 | 396 | @njit(parallel=True) 397 | def compute_long_run_median_parallel(w0=1, T=1000, num_reps=50_000): 398 | 399 | obs = np.empty(num_reps) 400 | for i in prange(num_reps): 401 | w = w0 402 | for t in range(T): 403 | w = h(w) 404 | obs[i] = w 405 | 406 | return np.median(obs) 407 | 408 | Let's look at the timing: 409 | 410 | .. code-block:: ipython 411 | 412 | %%time 413 | compute_long_run_median_parallel() 414 | 415 | The speed-up is significant. 416 | 417 | A Warning 418 | --------- 419 | 420 | Parallelization works well in the outer loop of the last example because the individual tasks inside the loop are independent of each other. 421 | 422 | If this independence fails then parallelization is often problematic. 423 | 424 | For example, each step inside the inner loop depends on the last step, so 425 | independence fails, and this is why we use ordinary ``range`` instead of ``prange``. 426 | 427 | When you see us using ``prange`` in later lectures, it is because the 428 | independence of tasks holds true. 429 | 430 | When you see us using ordinary ``range`` in a jitted function, it is either because the speed gain from parallelization is small or because independence fails. 431 | 432 | .. Dask 433 | 434 | .. To be added. 435 | 436 | 437 | .. GPUs 438 | 439 | .. Just say a few words about them. How do they relate to the foregoing? Explain that we can't introduce executable GPU code here. 440 | 441 | 442 | Exercises 443 | ========= 444 | 445 | Exercise 1 446 | ---------- 447 | 448 | In :ref:`an earlier exercise `, we used Numba to accelerate an 449 | effort to compute the constant :math:`\pi` by Monte Carlo. 450 | 451 | Now try adding parallelization and see if you get further speed gains. 452 | 453 | You should not expect huge gains here because, while there are many 454 | independent tasks (draw point and test if in circle), each one has low 455 | execution time. 456 | 457 | Generally speaking, parallelization is less effective when the individual 458 | tasks to be parallelized are very small relative to total execution time. 459 | 460 | This is due to overheads associated with spreading all of these small tasks across multiple CPUs. 461 | 462 | Nevertheless, with suitable hardware, it is possible to get nontrivial speed gains in this exercise. 463 | 464 | For the size of the Monte Carlo simulation, use something substantial, such as 465 | ``n = 100_000_000``. 466 | 467 | 468 | Solutions 469 | ========= 470 | 471 | Exercise 1 472 | ---------- 473 | 474 | Here is one solution: 475 | 476 | .. code-block:: python3 477 | 478 | from random import uniform 479 | 480 | @njit(parallel=True) 481 | def calculate_pi(n=1_000_000): 482 | count = 0 483 | for i in prange(n): 484 | u, v = uniform(0, 1), uniform(0, 1) 485 | d = np.sqrt((u - 0.5)**2 + (v - 0.5)**2) 486 | if d < 0.5: 487 | count += 1 488 | 489 | area_estimate = count / n 490 | return area_estimate * 4 # dividing by radius**2 491 | 492 | Now let's see how fast it runs: 493 | 494 | .. code-block:: ipython3 495 | 496 | %time calculate_pi() 497 | 498 | .. code-block:: ipython3 499 | 500 | %time calculate_pi() 501 | 502 | By switching parallelization on and off (selecting ``True`` or 503 | ``False`` in the ``@njit`` annotation), we can test the speed gain that 504 | multithreading provides on top of JIT compilation. 505 | 506 | On our workstation, we find that parallelization increases execution speed by 507 | a factor of 2 or 3. 508 | 509 | (If you are executing locally, you will get different numbers, depending mainly 510 | on the number of CPUs on your machine.) 511 | 512 | 513 | 514 | 515 | -------------------------------------------------------------------------------- /source/rst/search.rst: -------------------------------------------------------------------------------- 1 | .. _search: 2 | 3 | ********** 4 | Search 5 | ********** 6 | 7 | .. raw:: html 8 | 9 | 10 | 11 |
-------------------------------------------------------------------------------- /source/rst/status.rst: -------------------------------------------------------------------------------- 1 | .. _status: 2 | 3 | ************** 4 | Lecture Status 5 | ************** 6 | 7 | .. raw:: html 8 | 9 | 10 |

The badges below show which lectures are currently passing their execution test (i.e., executing without errors).

11 |

The lecture code checker was last run: N/A

12 |
13 |
14 |
15 |

The code checker is run on a t2.small Amazon EC2 instance. This is an instance with a single CPU and 2 GiB of Memory.

16 |

You should achieve faster run times on many common laptops and desktops.

-------------------------------------------------------------------------------- /source/rst/troubleshooting.rst: -------------------------------------------------------------------------------- 1 | .. _troubleshooting: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | .. highlight:: python3 6 | 7 | *************** 8 | Troubleshooting 9 | *************** 10 | 11 | .. contents:: :depth: 2 12 | 13 | This page is for readers experiencing errors when running the code from the lectures. 14 | 15 | Fixing Your Local Environment 16 | ============================== 17 | 18 | The basic assumption of the lectures is that code in a lecture should execute whenever 19 | 20 | #. it is executed in a Jupyter notebook and 21 | 22 | #. the notebook is running on a machine with the latest version of Anaconda Python. 23 | 24 | You have installed Anaconda, haven't you, following the instructions in :doc:`this lecture `? 25 | 26 | Assuming that you have, the most common source of problems for our readers is that their Anaconda distribution is not up to date. 27 | 28 | `Here's a useful article `__ 29 | on how to update Anaconda. 30 | 31 | Another option is to simply remove Anaconda and reinstall. 32 | 33 | You also need to keep the external code libraries, such as `QuantEcon.py 34 | `__ up to date. 35 | 36 | For this task you can either 37 | 38 | * use `conda upgrade quantecon` on the command line, or 39 | 40 | * execute `!conda upgrade quantecon` within a Jupyter notebook. 41 | 42 | If your local environment is still not working you can do two things. 43 | 44 | First, you can use a remote machine instead, by clicking on the `Launch Notebook` icon available for each lecture 45 | 46 | .. image:: _static/lecture_specific/troubleshooting/launch.png 47 | 48 | Second, you can report an issue, so we can try to fix your local set up. 49 | 50 | We like getting feedback on the lectures so please don't hesitate to get in 51 | touch. 52 | 53 | Reporting an Issue 54 | =================== 55 | 56 | One way to give feedback is to raise an issue through our `issue tracker 57 | `__. 58 | 59 | Please be as specific as possible. Tell us where the problem is and as much 60 | detail about your local set up as you can provide. 61 | 62 | Another feedback option is to use our `discourse forum `__. 63 | 64 | Finally, you can provide direct feedback to contact@quantecon.org 65 | 66 | -------------------------------------------------------------------------------- /source/rst/writing_good_code.rst: -------------------------------------------------------------------------------- 1 | .. _writing_good_code: 2 | 3 | .. include:: /_static/includes/header.raw 4 | 5 | .. highlight:: python3 6 | 7 | ***************** 8 | Writing Good Code 9 | ***************** 10 | 11 | .. index:: 12 | single: Models; Code style 13 | 14 | .. contents:: :depth: 2 15 | 16 | 17 | 18 | Overview 19 | ======== 20 | 21 | When computer programs are small, poorly written code is not overly costly. 22 | 23 | But more data, more sophisticated models, and more computer power are enabling us to take on more challenging problems that involve writing longer programs. 24 | 25 | For such programs, investment in good coding practices will pay high returns. 26 | 27 | The main payoffs are higher productivity and faster code. 28 | 29 | In this lecture, we review some elements of good coding practice. 30 | 31 | We also touch on modern developments in scientific computing --- such as just in time compilation --- and how they affect good program design. 32 | 33 | 34 | 35 | 36 | An Example of Poor Code 37 | ======================= 38 | 39 | Let's have a look at some poorly written code. 40 | 41 | The job of the code is to generate and plot time series of the simplified Solow model 42 | 43 | .. math:: 44 | :label: gc_solmod 45 | 46 | k_{t+1} = s k_t^{\alpha} + (1 - \delta) k_t, 47 | \quad t = 0, 1, 2, \ldots 48 | 49 | 50 | Here 51 | 52 | * :math:`k_t` is capital at time :math:`t` and 53 | 54 | * :math:`s, \alpha, \delta` are parameters (savings, a productivity parameter and depreciation) 55 | 56 | For each parameterization, the code 57 | 58 | #. sets :math:`k_0 = 1` 59 | 60 | #. iterates using :eq:`gc_solmod` to produce a sequence :math:`k_0, k_1, k_2 \ldots , k_T` 61 | 62 | #. plots the sequence 63 | 64 | The plots will be grouped into three subfigures. 65 | 66 | In each subfigure, two parameters are held fixed while another varies 67 | 68 | .. code-block:: ipython 69 | 70 | import numpy as np 71 | import matplotlib.pyplot as plt 72 | %matplotlib inline 73 | 74 | # Allocate memory for time series 75 | k = np.empty(50) 76 | 77 | fig, axes = plt.subplots(3, 1, figsize=(6, 14)) 78 | 79 | # Trajectories with different α 80 | δ = 0.1 81 | s = 0.4 82 | α = (0.25, 0.33, 0.45) 83 | 84 | for j in range(3): 85 | k[0] = 1 86 | for t in range(49): 87 | k[t+1] = s * k[t]**α[j] + (1 - δ) * k[t] 88 | axes[0].plot(k, 'o-', label=rf"$\alpha = {α[j]},\; s = {s},\; \delta={δ}$") 89 | 90 | axes[0].grid(lw=0.2) 91 | axes[0].set_ylim(0, 18) 92 | axes[0].set_xlabel('time') 93 | axes[0].set_ylabel('capital') 94 | axes[0].legend(loc='upper left', frameon=True) 95 | 96 | # Trajectories with different s 97 | δ = 0.1 98 | α = 0.33 99 | s = (0.3, 0.4, 0.5) 100 | 101 | for j in range(3): 102 | k[0] = 1 103 | for t in range(49): 104 | k[t+1] = s[j] * k[t]**α + (1 - δ) * k[t] 105 | axes[1].plot(k, 'o-', label=rf"$\alpha = {α},\; s = {s[j]},\; \delta={δ}$") 106 | 107 | axes[1].grid(lw=0.2) 108 | axes[1].set_xlabel('time') 109 | axes[1].set_ylabel('capital') 110 | axes[1].set_ylim(0, 18) 111 | axes[1].legend(loc='upper left', frameon=True) 112 | 113 | # Trajectories with different δ 114 | δ = (0.05, 0.1, 0.15) 115 | α = 0.33 116 | s = 0.4 117 | 118 | for j in range(3): 119 | k[0] = 1 120 | for t in range(49): 121 | k[t+1] = s * k[t]**α + (1 - δ[j]) * k[t] 122 | axes[2].plot(k, 'o-', label=rf"$\alpha = {α},\; s = {s},\; \delta={δ[j]}$") 123 | 124 | axes[2].set_ylim(0, 18) 125 | axes[2].set_xlabel('time') 126 | axes[2].set_ylabel('capital') 127 | axes[2].grid(lw=0.2) 128 | axes[2].legend(loc='upper left', frameon=True) 129 | 130 | plt.show() 131 | 132 | 133 | True, the code more or less follows `PEP8 `__. 134 | 135 | At the same time, it's very poorly structured. 136 | 137 | Let's talk about why that's the case, and what we can do about it. 138 | 139 | 140 | Good Coding Practice 141 | ==================== 142 | 143 | There are usually many different ways to write a program that accomplishes a given task. 144 | 145 | For small programs, like the one above, the way you write code doesn't matter too much. 146 | 147 | But if you are ambitious and want to produce useful things, you'll write medium to large programs too. 148 | 149 | In those settings, coding style matters **a great deal**. 150 | 151 | Fortunately, lots of smart people have thought about the best way to write code. 152 | 153 | Here are some basic precepts. 154 | 155 | 156 | 157 | Don't Use Magic Numbers 158 | ----------------------- 159 | 160 | If you look at the code above, you'll see numbers like ``50`` and ``49`` and ``3`` scattered through the code. 161 | 162 | These kinds of numeric literals in the body of your code are sometimes called "magic numbers". 163 | 164 | This is not a compliment. 165 | 166 | While numeric literals are not all evil, the numbers shown in the program above 167 | should certainly be replaced by named constants. 168 | 169 | For example, the code above could declare the variable ``time_series_length = 50``. 170 | 171 | Then in the loops, ``49`` should be replaced by ``time_series_length - 1``. 172 | 173 | The advantages are: 174 | 175 | * the meaning is much clearer throughout 176 | 177 | * to alter the time series length, you only need to change one value 178 | 179 | 180 | Don't Repeat Yourself 181 | --------------------- 182 | 183 | The other mortal sin in the code snippet above is repetition. 184 | 185 | Blocks of logic (such as the loop to generate time series) are repeated with only minor changes. 186 | 187 | This violates a fundamental tenet of programming: Don't repeat yourself (DRY). 188 | 189 | * Also called DIE (duplication is evil). 190 | 191 | Yes, we realize that you can just cut and paste and change a few symbols. 192 | 193 | But as a programmer, your aim should be to **automate** repetition, **not** do it yourself. 194 | 195 | More importantly, repeating the same logic in different places means that eventually one of them will likely be wrong. 196 | 197 | If you want to know more, read the excellent summary found on `this page `__. 198 | 199 | We'll talk about how to avoid repetition below. 200 | 201 | 202 | Minimize Global Variables 203 | ------------------------- 204 | 205 | Sure, global variables (i.e., names assigned to values outside of any function or class) are convenient. 206 | 207 | Rookie programmers typically use global variables with abandon --- as we once did ourselves. 208 | 209 | But global variables are dangerous, especially in medium to large size programs, since 210 | 211 | * they can affect what happens in any part of your program 212 | 213 | * they can be changed by any function 214 | 215 | This makes it much harder to be certain about what some small part of a given piece of code actually commands. 216 | 217 | Here's a `useful discussion on the topic `__. 218 | 219 | While the odd global in small scripts is no big deal, we recommend that you teach yourself to avoid them. 220 | 221 | (We'll discuss how just below). 222 | 223 | 224 | JIT Compilation 225 | ^^^^^^^^^^^^^^^ 226 | 227 | For scientific computing, there is another good reason to avoid global variables. 228 | 229 | As :doc:`we've seen in previous lectures `, JIT compilation can generate excellent performance for scripting languages like Python. 230 | 231 | But the task of the compiler used for JIT compilation becomes harder when global variables are present. 232 | 233 | Put differently, the type inference required for JIT compilation is safer and 234 | more effective when variables are sandboxed inside a function. 235 | 236 | 237 | Use Functions or Classes 238 | ------------------------ 239 | 240 | Fortunately, we can easily avoid the evils of global variables and WET code. 241 | 242 | * WET stands for "we enjoy typing" and is the opposite of DRY. 243 | 244 | We can do this by making frequent use of functions or classes. 245 | 246 | In fact, functions and classes are designed specifically to help us avoid shaming ourselves by repeating code or excessive use of global variables. 247 | 248 | 249 | Which One, Functions or Classes? 250 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 251 | 252 | Both can be useful, and in fact they work well with each other. 253 | 254 | We'll learn more about these topics over time. 255 | 256 | (Personal preference is part of the story too) 257 | 258 | What's really important is that you use one or the other or both. 259 | 260 | 261 | 262 | Revisiting the Example 263 | ====================== 264 | 265 | Here's some code that reproduces the plot above with better coding style. 266 | 267 | 268 | .. code-block:: python3 269 | 270 | from itertools import product 271 | 272 | def plot_path(ax, αs, s_vals, δs, time_series_length=50): 273 | """ 274 | Add a time series plot to the axes ax for all given parameters. 275 | """ 276 | k = np.empty(time_series_length) 277 | 278 | for (α, s, δ) in product(αs, s_vals, δs): 279 | k[0] = 1 280 | for t in range(time_series_length-1): 281 | k[t+1] = s * k[t]**α + (1 - δ) * k[t] 282 | ax.plot(k, 'o-', label=rf"$\alpha = {α},\; s = {s},\; \delta = {δ}$") 283 | 284 | ax.set_xlabel('time') 285 | ax.set_ylabel('capital') 286 | ax.set_ylim(0, 18) 287 | ax.legend(loc='upper left', frameon=True) 288 | 289 | fig, axes = plt.subplots(3, 1, figsize=(6, 14)) 290 | 291 | # Parameters (αs, s_vals, δs) 292 | set_one = ([0.25, 0.33, 0.45], [0.4], [0.1]) 293 | set_two = ([0.33], [0.3, 0.4, 0.5], [0.1]) 294 | set_three = ([0.33], [0.4], [0.05, 0.1, 0.15]) 295 | 296 | for (ax, params) in zip(axes, (set_one, set_two, set_three)): 297 | αs, s_vals, δs = params 298 | plot_path(ax, αs, s_vals, δs) 299 | 300 | plt.show() 301 | 302 | 303 | If you inspect this code, you will see that 304 | 305 | * it uses a function to avoid repetition. 306 | * Global variables are quarantined by collecting them together at the end, not the start of the program. 307 | * Magic numbers are avoided. 308 | * The loop at the end where the actual work is done is short and relatively simple. 309 | 310 | Exercises 311 | ========= 312 | 313 | Exercise 1 314 | ---------- 315 | 316 | Here is some code that needs improving. 317 | 318 | It involves a basic supply and demand problem. 319 | 320 | Supply is given by 321 | 322 | .. math:: q_s(p) = \exp(\alpha p) - \beta. 323 | 324 | The demand curve is 325 | 326 | .. math:: q_d(p) = \gamma p^{-\delta}. 327 | 328 | The values :math:`\alpha`, :math:`\beta`, :math:`\gamma` and 329 | :math:`\delta` are **parameters** 330 | 331 | The equilibrium :math:`p^*` is the price such that 332 | :math:`q_d(p) = q_s(p)`. 333 | 334 | We can solve for this equilibrium using a root finding algorithm. 335 | Specifically, we will find the :math:`p` such that :math:`h(p) = 0`, 336 | where 337 | 338 | .. math:: h(p) := q_d(p) - q_s(p) 339 | 340 | This yields the equilibrium price :math:`p^*`. From this we get the 341 | equilibrium price by :math:`q^* = q_s(p^*)` 342 | 343 | The parameter values will be 344 | 345 | - :math:`\alpha = 0.1` 346 | - :math:`\beta = 1` 347 | - :math:`\gamma = 1` 348 | - :math:`\delta = 1` 349 | 350 | .. code:: ipython3 351 | 352 | from scipy.optimize import brentq 353 | 354 | # Compute equilibrium 355 | def h(p): 356 | return p**(-1) - (np.exp(0.1 * p) - 1) # demand - supply 357 | 358 | p_star = brentq(h, 2, 4) 359 | q_star = np.exp(0.1 * p_star) - 1 360 | 361 | print(f'Equilibrium price is {p_star: .2f}') 362 | print(f'Equilibrium quantity is {q_star: .2f}') 363 | 364 | Let's also plot our results. 365 | 366 | .. code:: ipython3 367 | 368 | # Now plot 369 | grid = np.linspace(2, 4, 100) 370 | fig, ax = plt.subplots() 371 | 372 | qs = np.exp(0.1 * grid) - 1 373 | qd = grid**(-1) 374 | 375 | 376 | ax.plot(grid, qd, 'b-', lw=2, label='demand') 377 | ax.plot(grid, qs, 'g-', lw=2, label='supply') 378 | 379 | ax.set_xlabel('price') 380 | ax.set_ylabel('quantity') 381 | ax.legend(loc='upper center') 382 | 383 | plt.show() 384 | 385 | We also want to consider supply and demand shifts. 386 | 387 | For example, let's see what happens when demand shifts up, with :math:`\gamma` increasing to :math:`1.25`: 388 | 389 | .. code:: ipython3 390 | 391 | # Compute equilibrium 392 | def h(p): 393 | return 1.25 * p**(-1) - (np.exp(0.1 * p) - 1) 394 | 395 | p_star = brentq(h, 2, 4) 396 | q_star = np.exp(0.1 * p_star) - 1 397 | 398 | print(f'Equilibrium price is {p_star: .2f}') 399 | print(f'Equilibrium quantity is {q_star: .2f}') 400 | 401 | .. code:: ipython3 402 | 403 | # Now plot 404 | p_grid = np.linspace(2, 4, 100) 405 | fig, ax = plt.subplots() 406 | 407 | qs = np.exp(0.1 * p_grid) - 1 408 | qd = 1.25 * p_grid**(-1) 409 | 410 | 411 | ax.plot(grid, qd, 'b-', lw=2, label='demand') 412 | ax.plot(grid, qs, 'g-', lw=2, label='supply') 413 | 414 | ax.set_xlabel('price') 415 | ax.set_ylabel('quantity') 416 | ax.legend(loc='upper center') 417 | 418 | plt.show() 419 | 420 | 421 | Now we might consider supply shifts, but you already get the idea that there's 422 | a lot of repeated code here. 423 | 424 | Refactor and improve clarity in the code above using the principles discussed 425 | in this lecture. 426 | 427 | 428 | 429 | Solutions 430 | ========= 431 | 432 | Exercise 1 433 | ---------- 434 | 435 | Here's one solution, that uses a class: 436 | 437 | 438 | .. code:: ipython3 439 | 440 | class Equilibrium: 441 | 442 | def __init__(self, α=0.1, β=1, γ=1, δ=1): 443 | self.α, self.β, self.γ, self.δ = α, β, γ, δ 444 | 445 | def qs(self, p): 446 | return np.exp(self.α * p) - self.β 447 | 448 | def qd(self, p): 449 | return self.γ * p**(-self.δ) 450 | 451 | def compute_equilibrium(self): 452 | def h(p): 453 | return self.qd(p) - self.qs(p) 454 | p_star = brentq(h, 2, 4) 455 | q_star = np.exp(self.α * p_star) - self.β 456 | 457 | print(f'Equilibrium price is {p_star: .2f}') 458 | print(f'Equilibrium quantity is {q_star: .2f}') 459 | 460 | def plot_equilibrium(self): 461 | # Now plot 462 | grid = np.linspace(2, 4, 100) 463 | fig, ax = plt.subplots() 464 | 465 | ax.plot(grid, self.qd(grid), 'b-', lw=2, label='demand') 466 | ax.plot(grid, self.qs(grid), 'g-', lw=2, label='supply') 467 | 468 | ax.set_xlabel('price') 469 | ax.set_ylabel('quantity') 470 | ax.legend(loc='upper center') 471 | 472 | plt.show() 473 | 474 | Let's create an instance at the default parameter values. 475 | 476 | .. code:: ipython3 477 | 478 | eq = Equilibrium() 479 | 480 | Now we'll compute the equilibrium and plot it. 481 | 482 | .. code:: ipython3 483 | 484 | eq.compute_equilibrium() 485 | 486 | .. code:: ipython3 487 | 488 | eq.plot_equilibrium() 489 | 490 | One of the nice things about our refactored code is that, when we change 491 | parameters, we don't need to repeat ourselves: 492 | 493 | .. code:: ipython3 494 | 495 | eq.γ = 1.25 496 | 497 | .. code:: ipython3 498 | 499 | eq.compute_equilibrium() 500 | 501 | .. code:: ipython3 502 | 503 | eq.plot_equilibrium() 504 | 505 | -------------------------------------------------------------------------------- /theme/minimal/static/css/qe.python.css: -------------------------------------------------------------------------------- 1 | /* Homepage */ 2 | .home-intro { 3 | display: flex; 4 | align-content: center; 5 | } 6 | .home-blurb { 7 | font-size: 1.1rem; 8 | line-height: 1.5; 9 | } 10 | .home-intro .sponsor { 11 | list-style: none; 12 | padding:0; 13 | flex-shrink: 0; 14 | margin:0 60px 0 4rem; 15 | text-align: center; 16 | } 17 | .home-intro .sponsor li { 18 | display: block; 19 | margin:1rem 0; 20 | padding:0; 21 | } 22 | .web-version { 23 | display:inline-block; 24 | padding: 2rem 0rem; 25 | } 26 | .web-version a { 27 | display: block; 28 | padding:1rem 40px 1rem 80px; 29 | position: relative; 30 | } 31 | .web-version a .thumb { 32 | position: absolute; 33 | left:0px; 34 | top:1rem; 35 | } 36 | .web-version a .thumb img { 37 | width:50px; 38 | } 39 | .web-version a h2 { 40 | line-height: 1; 41 | margin:0; 42 | font-size: 1.4rem; 43 | } 44 | .web-version a p { 45 | margin:10px 0 0 0; 46 | } 47 | .home-alternatives { 48 | padding: 1rem 0rem; 49 | } 50 | .home-alternatives ul { 51 | list-style: none; 52 | padding:0; 53 | margin:0 0; 54 | } 55 | .home-alternatives li { 56 | padding:0; 57 | margin:1rem 1rem; 58 | } 59 | .home-alternatives li a { 60 | display: block; 61 | } 62 | .home-alternatives li a h3 { 63 | line-height: 1; 64 | margin:0; 65 | font-size: 1.2rem; 66 | } 67 | .home-alternatives li a p { 68 | margin:10px 0 0 0; 69 | } 70 | @media only screen and (max-width: 768px) { 71 | .home-intro { 72 | display: block; 73 | } 74 | .home-intro .sponsor { 75 | margin:0 auto; 76 | } 77 | } 78 | 79 | 80 | /* Other */ 81 | #qe-notebook-header { 82 | display: none; 83 | } -------------------------------------------------------------------------------- /theme/minimal/static/img/code-block-fade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/theme/minimal/static/img/code-block-fade.png -------------------------------------------------------------------------------- /theme/minimal/static/img/powered-by-NumFOCUS-orange.svg: -------------------------------------------------------------------------------- 1 | powered bypowered byNumFOCUSNumFOCUS -------------------------------------------------------------------------------- /theme/minimal/static/img/py-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/theme/minimal/static/img/py-logo.png -------------------------------------------------------------------------------- /theme/minimal/static/img/qe-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/theme/minimal/static/img/qe-logo.png -------------------------------------------------------------------------------- /theme/minimal/static/img/search-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/theme/minimal/static/img/search-icon.png -------------------------------------------------------------------------------- /theme/minimal/static/img/sloan_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/theme/minimal/static/img/sloan_logo.png -------------------------------------------------------------------------------- /theme/minimal/static/js/base.js: -------------------------------------------------------------------------------- 1 | // base.js v1.0 2 | 3 | 4 | // Declare MathJax Macros for the Appropriate Macros 5 | MathJax.Hub.Config({ 6 | TeX: { 7 | Macros: { 8 | Var: "\\mathop{\\mathrm{Var}}", 9 | trace: "\\mathop{\\mathrm{trace}}", 10 | argmax: "\\mathop{\\mathrm{arg\\,max}}", 11 | argmin: "\\mathop{\\mathrm{arg\\,min}}", 12 | proj: "\\mathop{\\mathrm{proj}}", 13 | col: "\\mathop{\\mathrm{col}}", 14 | Span: "\\mathop{\\mathrm{span}}", 15 | epsilon: "\\varepsilon", 16 | EE: "\\mathbb{E}", 17 | PP: "\\mathbb{P}", 18 | RR: "\\mathbb{R}", 19 | NN: "\\mathbb{N}", 20 | ZZ: "\\mathbb{Z}", 21 | aA: "\\mathcal{A}", 22 | bB: "\\mathcal{B}", 23 | cC: "\\mathcal{C}", 24 | dD: "\\mathcal{D}", 25 | eE: "\\mathcal{E}", 26 | fF: "\\mathcal{F}", 27 | gG: "\\mathcal{G}", 28 | hH: "\\mathcal{H}", 29 | } 30 | } 31 | }); 32 | MathJax.Hub.Config({ 33 | tex2jax: { 34 | inlineMath: [ ['$','$'], ['\\(','\\)'] ], 35 | processEscapes: true 36 | } 37 | }); 38 | 39 | 40 | /* Collapsed code block */ 41 | 42 | const collapsableCodeBlocks = document.querySelectorAll("div[class^='collapse'] .highlight"); 43 | for (var i = 0; i < collapsableCodeBlocks.length; i++) { 44 | const toggleContainer = document.createElement('div'); 45 | toggleContainer.innerHTML = 'Show more...'; 46 | collapsableCodeBlocks[i].parentNode.insertBefore(toggleContainer, collapsableCodeBlocks[i].nextSibling); 47 | } 48 | 49 | const collapsableCodeToggles = document.querySelectorAll("div[class^='collapse'] .toggle"); 50 | for (var i = 0; i < collapsableCodeToggles.length; i++) { 51 | collapsableCodeToggles[i].addEventListener('click', function(e) { 52 | e.preventDefault(); 53 | var codeBlock = this.closest('div[class^="collapse"]'); 54 | if ( codeBlock.classList.contains('expanded') ) { 55 | codeBlock.classList.remove('expanded'); 56 | this.style.display = 'none'; 57 | this.nextSibling.style.display = 'block'; 58 | } else { 59 | codeBlock.classList.add('expanded'); 60 | this.style.display = 'none'; 61 | this.previousSibling.style.display = 'block'; 62 | } 63 | }); 64 | } 65 | 66 | 67 | /* Wrap container around all tables allowing hirizontal scroll */ 68 | 69 | const contentTables = document.querySelectorAll(".content table"); 70 | for (var i = 0; i < contentTables.length; i++) { 71 | var wrapper = document.createElement('div'); 72 | wrapper.classList.add('table-container'); 73 | contentTables[i].parentNode.insertBefore(wrapper, contentTables[i]); 74 | wrapper.appendChild(contentTables[i]); 75 | } 76 | 77 | 78 | // Populate status page from code execution results JSON 79 | 80 | function loadCodeExecutionJSON(callback) { 81 | var xobj = new XMLHttpRequest(); 82 | xobj.overrideMimeType("application/json"); 83 | xobj.open('GET', '_static/code-execution-results.json', true); // Replace 'appDataServices' with the path to your file 84 | xobj.onreadystatechange = function () { 85 | if (xobj.readyState == 4 && xobj.status == "200") { 86 | // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode 87 | callback(xobj.responseText); 88 | } 89 | }; 90 | xobj.send(null); 91 | } 92 | 93 | if ( document.getElementById('status_table') ) { 94 | 95 | loadCodeExecutionJSON(function(response) { 96 | // Parsing JSON string into object 97 | var data = JSON.parse(response); 98 | var status_data = []; 99 | var last_test_time = data.run_time; 100 | document.getElementById('last_test_time').textContent = last_test_time; 101 | for (var key in data.results) 102 | { 103 | var new_record = {}; 104 | new_record['name'] = data.results[key].filename; 105 | new_record['runtime'] = data.results[key].runtime; 106 | new_record['extension'] = data.results[key].extension; 107 | new_record['result'] = data.results[key].num_errors; 108 | new_record['language'] = data.results[key].language; 109 | 110 | status_data.push(new_record); 111 | } 112 | 113 | // empty the table 114 | var table = document.getElementById("status_table"); 115 | while (table.firstChild) 116 | table.removeChild(table.firstChild); 117 | var rawHTML = "Lecture FileLanguageRunning Time"; 118 | table.innerHTML = rawHTML; 119 | // add the data 120 | for (var i = 0; i < status_data.length; i ++) 121 | { 122 | var table = document.getElementById("status_table"); 123 | var row = table.insertRow(-1); 124 | row.setAttribute("id", status_data[i]['name'], 0); 125 | 126 | // Insert new cells ( elements) at the 1st and 2nd position of the "new" element: 127 | var lectureCell = row.insertCell(0); 128 | var langCell = row.insertCell(1); 129 | var runtimeCell = row.insertCell(2); 130 | var statusCell = row.insertCell(3); 131 | var badge, status, color, lang, link; 132 | 133 | if (status_data[i]['result'] === 0) 134 | { 135 | status = "Passing"; 136 | color = "brightgreen"; 137 | } 138 | else if (status_data[i]['result'] === 1) 139 | { 140 | status = "Failing"; 141 | color = "red"; 142 | } 143 | else if (status_data[i]['result'] === -1) { 144 | status = "Not available"; 145 | color = "lightgrey"; 146 | } 147 | 148 | link = '/' + status_data[i]['name'] + '.html'; 149 | 150 | badge = ''; 151 | 152 | // Add some text to the new cells: 153 | lectureCell.innerHTML = status_data[i]['name']; 154 | langCell.innerHTML = status_data[i]['language']; 155 | runtimeCell.innerHTML = status_data[i]['runtime']; 156 | statusCell.innerHTML = badge; 157 | 158 | 159 | } 160 | }) 161 | } 162 | 163 | 164 | // Show executability status badge in header 165 | 166 | const LECTURE_OK = 0; 167 | const LECTURE_FAILED = 1; 168 | const LECTURE_ERROR = -1; 169 | 170 | function update_page_badge(page_status) 171 | { 172 | var badge = document.getElementById("executability_status_badge"); 173 | var status, color; 174 | 175 | if (page_status === LECTURE_OK) 176 | { 177 | status = "Passing"; 178 | color = "brightgreen"; 179 | } 180 | else if (page_status == LECTURE_FAILED) 181 | { 182 | status = "Failing"; 183 | color = "red"; 184 | } 185 | else if (page_status == LECTURE_ERROR) 186 | { 187 | status = "Not available"; 188 | color = "lightgrey"; 189 | } 190 | else 191 | { 192 | console.log("Panic! Invalid parameter passed to update_page_badge()."); 193 | } 194 | 195 | badge.innerHTML = ''; 196 | 197 | //badge.style.display="block"; 198 | 199 | return; 200 | } 201 | 202 | function determine_page_status(status_data) 203 | { 204 | var path = window.location.pathname; 205 | var filename_parts = path.split("/"); 206 | var filename = filename_parts.pop(); 207 | 208 | var lecture_name = filename.split(".")[0].toLowerCase(); 209 | 210 | var res = LECTURE_ERROR; 211 | 212 | for (var i = 0; i < status_data.length; i ++) 213 | { 214 | if (status_data[i]['name'].split('/').pop() === lecture_name) 215 | { 216 | if (status_data[i]['result'] === 0) 217 | { 218 | res = LECTURE_OK; 219 | } 220 | else 221 | { 222 | res = LECTURE_FAILED; 223 | } 224 | } 225 | } 226 | return res; 227 | } 228 | 229 | function load_this_page_badge() 230 | { 231 | loadCodeExecutionJSON(function(response) { 232 | // Parsing JSON string into object 233 | var data = JSON.parse(response); 234 | status_data = []; 235 | for (var key in data.results) 236 | { 237 | var new_record = {}; 238 | new_record['name'] = data.results[key].filename; 239 | new_record['runtime'] = data.results[key].runtime; 240 | new_record['extension'] = data.results[key].extension; 241 | new_record['result'] = data.results[key].num_errors; 242 | new_record['language'] = data.results[key].language; 243 | status_data.push(new_record); 244 | } 245 | var page_status = determine_page_status(status_data); 246 | update_page_badge(page_status); 247 | }); 248 | } 249 | 250 | function get_badge(percentage) 251 | { 252 | var color, badge; 253 | 254 | if (percentage > -1) 255 | { 256 | if ( percentage < 50 ) { 257 | color = 'red'; 258 | } else { 259 | color = 'brightgreen'; 260 | } 261 | badge = 'https://img.shields.io/badge/Total%20coverage-' + percentage + '%25-' + color + '.svg'; 262 | } else { 263 | badge = 'https://img.shields.io/badge/Total%20coverage-not%20available-lightgrey.svg>'; 264 | } 265 | return badge; 266 | } 267 | 268 | function load_percentages() 269 | { 270 | var number_of_lectures = {}; 271 | var number_which_passed = {}; 272 | var keys_list = []; 273 | var combined_percentage; 274 | 275 | loadCodeExecutionJSON(function(response) { 276 | // Parsing JSON string into object 277 | var data = JSON.parse(response); 278 | for (var key in data.results) 279 | { 280 | if (data.results[key].num_errors === 0) 281 | { 282 | if (!(data.results[key].extension in number_which_passed)) 283 | { 284 | number_which_passed[data.results[key].extension] = 0; 285 | keys_list.push(data.results[key].extension); 286 | } 287 | number_which_passed[data.results[key].extension] += 1; 288 | } 289 | 290 | if (!(data.results[key].extension in number_of_lectures)) 291 | { 292 | number_of_lectures[data.results[key].extension] = 0; 293 | } 294 | number_of_lectures[data.results[key].extension] += 1; 295 | } 296 | 297 | var percentages = {}; 298 | var total_lectures = 0; 299 | var total_passing = 0; 300 | for (var k in keys_list) 301 | { 302 | key = keys_list[k]; 303 | 304 | percentages[key] = 0; 305 | if (number_of_lectures[key] === 0) 306 | { 307 | // An appropriate value for this is yet to be determined. 308 | percentages[key] = 100; 309 | } 310 | else 311 | { 312 | percentages[key] = Math.floor(100 * number_which_passed[key] / number_of_lectures[key]); 313 | } 314 | 315 | // Sensible boundary checking. 316 | if (percentages[key] < 0 || percentages[key] > 100) 317 | { 318 | percentages[key] = -1; 319 | } 320 | 321 | total_lectures += number_of_lectures[key]; 322 | total_passing += number_which_passed[key]; 323 | } 324 | 325 | if (total_lectures === 0) 326 | { 327 | combined_percentage = 0; 328 | } 329 | else 330 | { 331 | combined_percentage = Math.floor(100 * total_passing / total_lectures); 332 | } 333 | 334 | var badge = document.getElementById("coverage_badge"); 335 | badge.innerHTML = ''; 336 | 337 | }); 338 | 339 | } 340 | 341 | if ( document.getElementById('executability_status_badge') ) { 342 | load_this_page_badge(); 343 | } 344 | 345 | if ( document.getElementById('coverage_badge') ) { 346 | load_percentages(); 347 | } -------------------------------------------------------------------------------- /theme/minimal/static/sloan_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantEcon/lecture-python-programming/091018cf834f937462222e24045cde581e5357ea/theme/minimal/static/sloan_logo.png -------------------------------------------------------------------------------- /theme/minimal/templates/error_report_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Jupyter Script Test Execution - Error Report 4 | 5 | 6 | 7 | 8 | 9 | 10 |

Error Report - Generated {DATETIME}

11 | 12 |

13 | Overview 14 |

15 | 16 | {ERROR_SUMMARY} 17 | 18 | {NOTEBOOK_LOOP} 19 | 20 | 21 | -------------------------------------------------------------------------------- /theme/minimal/templates/html.tpl: -------------------------------------------------------------------------------- 1 | {%- extends 'display_priority.tpl' -%} 2 | 3 | {% set site_title = 'Lectures' %} 4 | {% set nb_title = nb.metadata.get('title', '') %} 5 | {% set nb_filename = nb.metadata.get('filename', '') %} 6 | {% set nb_filename_with_path = nb.metadata.get('filename_with_path','') %} 7 | {% set indexPage = nb_filename.startswith('index') %} 8 | {% set download_nb = nb.metadata.get('download_nb','') %} 9 | {% set download_nb_path = nb.metadata.get('download_nb_path','') %} 10 | {% if nb_filename.endswith('.rst') %} 11 | {% set nb_filename = nb_filename[:-4] %} 12 | {% endif %} 13 | 14 | {%- block header %} 15 | 16 | 17 | 18 | 19 | {% if nb_filename == 'index' %} 20 | {{ site_title }} 21 | {% else %} 22 | {{nb_title}} – {{ site_title }} 23 | {% endif %} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | 38 |
39 | 40 |
41 | 42 |

{{ site_title }}

43 | 44 |

Skip to content

45 | 46 |
47 | 48 |
49 | 50 | {% if indexPage or nb_filename == 'status' %} 51 |
52 | {% else %} 53 |
54 | {% endif %} 55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 | 64 | 65 | 66 |
67 | 68 | {%- endblock header-%} 69 | 70 | {% block codecell %} 71 | {% set html_class = cell['metadata'].get('html-class', {}) %} 72 |
73 | {{ super() }} 74 |
75 | {%- endblock codecell %} 76 | 77 | {% block input_group -%} 78 |
79 | {{ super() }} 80 |
81 | {% endblock input_group %} 82 | 83 | {% block output_group %} 84 |
85 |
86 | {{ super() }} 87 |
88 |
89 | {% endblock output_group %} 90 | 91 | {% block in_prompt -%} 92 |
93 | {%- if cell.execution_count is defined -%} 94 | In [{{ cell.execution_count|replace(None, " ") }}]: 95 | {%- else -%} 96 | In [ ]: 97 | {%- endif -%} 98 |
99 | {%- endblock in_prompt %} 100 | 101 | {% block empty_in_prompt -%} 102 |
103 |
104 | {%- endblock empty_in_prompt %} 105 | 106 | {# 107 | output_prompt doesn't do anything in HTML, 108 | because there is a prompt div in each output area (see output block) 109 | #} 110 | {% block output_prompt %} 111 | {% endblock output_prompt %} 112 | 113 | {% block input %} 114 |
115 |
116 | {{ cell.source | highlight_code(metadata=cell.metadata) }} 117 |
118 |
119 | {%- endblock input %} 120 | 121 | {% block output_area_prompt %} 122 | {%- if output.output_type == 'execute_result' -%} 123 |
124 | {%- if cell.execution_count is defined -%} 125 | Out[{{ cell.execution_count|replace(None, " ") }}]: 126 | {%- else -%} 127 | Out[ ]: 128 | {%- endif -%} 129 | {%- else -%} 130 |
131 | {%- endif -%} 132 |
133 | {% endblock output_area_prompt %} 134 | 135 | {% block output %} 136 |
137 | {% if resources.global_content_filter.include_output_prompt %} 138 | {{ self.output_area_prompt() }} 139 | {% endif %} 140 | {{ super() }} 141 |
142 | {% endblock output %} 143 | 144 | {% block markdowncell scoped %} 145 | {% set html_class = cell['metadata'].get('html-class', {}) %} 146 |
147 | {%- if resources.global_content_filter.include_input_prompt-%} 148 | {{ self.empty_in_prompt() }} 149 | {%- endif -%} 150 |
151 |
152 | {{ cell.source | markdown2html | strip_files_prefix }} 153 |
154 |
155 |
156 | {%- endblock markdowncell %} 157 | 158 | {% block unknowncell scoped %} 159 | unknown type {{ cell.type }} 160 | {% endblock unknowncell %} 161 | 162 | {% block execute_result -%} 163 | {%- set extra_class="output_execute_result" -%} 164 | {% block data_priority scoped %} 165 | {{ super() }} 166 | {% endblock data_priority %} 167 | {%- set extra_class="" -%} 168 | {%- endblock execute_result %} 169 | 170 | {% block stream_stdout -%} 171 |
172 |
173 | {{- output.text | ansi2html -}}
174 | 
175 |
176 | {%- endblock stream_stdout %} 177 | 178 | {% block stream_stderr -%} 179 |
180 |
181 | {{- output.text | ansi2html -}}
182 | 
183 |
184 | {%- endblock stream_stderr %} 185 | 186 | {% block data_svg scoped -%} 187 |
188 | {%- if output.svg_filename %} 189 | 194 | {%- endblock data_svg %} 195 | 196 | {% block data_html scoped -%} 197 |
198 | {{ output.data['text/html'] }} 199 |
200 | {%- endblock data_html %} 201 | 202 | {% block data_markdown scoped -%} 203 |
204 | {{ output.data['text/markdown'] | markdown2html }} 205 |
206 | {%- endblock data_markdown %} 207 | 208 | {% block data_png scoped %} 209 |
210 | {%- if 'image/png' in output.metadata.get('filenames', {}) %} 211 | 227 |
228 | {%- endblock data_png %} 229 | 230 | {% block data_jpg scoped %} 231 |
232 | {%- if 'image/jpeg' in output.metadata.get('filenames', {}) %} 233 | 249 |
250 | {%- endblock data_jpg %} 251 | 252 | {% block data_latex scoped %} 253 |
254 | {{ output.data['text/latex'] }} 255 |
256 | {%- endblock data_latex %} 257 | 258 | {% block error -%} 259 |
260 |
261 | {{- super() -}}
262 | 
263 |
264 | {%- endblock error %} 265 | 266 | {%- block traceback_line %} 267 | {{ line | ansi2html }} 268 | {%- endblock traceback_line %} 269 | 270 | {%- block data_text scoped %} 271 |
272 |
273 | {{- output.data['text/plain'] | ansi2html -}}
274 | 
275 |
276 | {%- endblock -%} 277 | 278 | {%- block data_javascript scoped %} 279 | {% set div_id = uuid4() %} 280 |
281 |
282 | 286 |
287 | {%- endblock -%} 288 | 289 | {%- block data_widget_state scoped %} 290 | {% set div_id = uuid4() %} 291 | {% set datatype_list = output.data | filter_data_type %} 292 | {% set datatype = datatype_list[0]%} 293 |
294 |
295 | 298 | 301 |
302 | {%- endblock data_widget_state -%} 303 | 304 | {%- block data_widget_view scoped %} 305 | {% set div_id = uuid4() %} 306 | {% set datatype_list = output.data | filter_data_type %} 307 | {% set datatype = datatype_list[0]%} 308 |
309 |
310 | 313 | 316 |
317 | {%- endblock data_widget_view -%} 318 | 319 | {%- block footer %} 320 | {% set mimetype = 'application/vnd.jupyter.widget-state+json'%} 321 | {% if mimetype in nb.metadata.get("widgets",{})%} 322 | 325 | {% endif %} 326 | {{ super() }} 327 | 328 | 329 |
330 | 331 |
332 | 333 |
334 | 335 |
336 | 337 |

© Copyright XXXX, Occaecat ipsum culpa nulla in Lorem dolor exercitation adipisicing in qui pariatur.

338 | 339 |
340 | 341 |
342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | {%- endblock footer-%} 351 | -------------------------------------------------------------------------------- /theme/minimal/templates/latex.tpl: -------------------------------------------------------------------------------- 1 | ((*- extends 'article.tplx' -*)) 2 | 3 | % See http://blog.juliusschulz.de/blog/ultimate-ipython-notebook#templates 4 | % for some useful tips 5 | 6 | %=============================================================================== 7 | % Document class 8 | %=============================================================================== 9 | 10 | ((* block docclass *)) 11 | \documentclass[11pt, twoside, a4paper]{article} 12 | ((* endblock docclass *)) 13 | 14 | %=============================================================================== 15 | % Packages 16 | %=============================================================================== 17 | 18 | ((* block packages *)) 19 | \usepackage[T1]{fontenc} 20 | \usepackage{graphicx} 21 | \usepackage[breakable]{tcolorbox} 22 | % We will generate all images so they have a width \maxwidth. This means 23 | % that they will get their normal width if they fit onto the page, but 24 | % are scaled down if they would overflow the margins. 25 | \makeatletter 26 | \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth 27 | \else\Gin@nat@width\fi} 28 | \makeatother 29 | \let\Oldincludegraphics\includegraphics 30 | 31 | % propose delete% 32 | % Ensure that by default, figures have no caption (until we provide a 33 | % proper Figure object with a Caption API and a way to capture that 34 | % in the conversion process - todo). 35 | % \usepackage{caption} 36 | % \DeclareCaptionLabelFormat{empty}{} 37 | %\captionsetup{format=empty,aboveskip=0pt,belowskip=0pt} 38 | % end - propose delete% 39 | 40 | % float figure settings% 41 | \usepackage{float} 42 | \floatplacement{figure}{H} % used to force figures for placement in text 43 | 44 | \usepackage{adjustbox} % Used to constrain images to a maximum size 45 | \usepackage{xcolor} % Allow colors to be defined 46 | \usepackage{enumerate} % Needed for markdown enumerations to work 47 | \usepackage{geometry} % Used to adjust the document margins 48 | \usepackage{amsmath} % Equations 49 | \usepackage{amssymb} % Equations 50 | \usepackage{textcomp} % defines textquotesingle 51 | % Hack from http://tex.stackexchange.com/a/47451/13684: 52 | \AtBeginDocument{% 53 | \def\PYZsq{\textquotesingle}% Upright quotes in Pygmentized code 54 | } 55 | \usepackage{upquote} % Upright quotes for verbatim code 56 | \usepackage{eurosym} % defines \euro 57 | \usepackage[mathletters]{ucs} % Extended unicode (utf-8) support 58 | \usepackage[utf8x]{inputenc} % Allow utf-8 characters in the tex document 59 | \usepackage{fancyvrb} % verbatim replacement that allows latex 60 | \usepackage{xcolor} 61 | \usepackage{listings} 62 | \lstset{escapeinside={<@}{@>}} 63 | \usepackage{grffile} % extends the file name processing of package graphics 64 | % to support a larger range 65 | % The hyperref package gives us a pdf with properly built 66 | % internal navigation ('pdf bookmarks' for the table of contents, 67 | % internal cross-reference links, web links for URLs, etc.) 68 | \usepackage{hyperref} 69 | \usepackage{longtable} % longtable support required by pandoc >1.10 70 | \usepackage{booktabs} % table support for pandoc > 1.12.2 71 | \usepackage[inline]{enumitem} % IRkernel/repr support (it uses the enumerate* environment) 72 | \usepackage[normalem]{ulem} % ulem is needed to support strikethroughs (\sout) 73 | % normalem makes italics be italics, not underlines 74 | \usepackage{braket} 75 | \usepackage{mathrsfs} 76 | \usepackage{natbib} 77 | \usepackage[document]{ragged2e} 78 | \usepackage{fontspec, unicode-math} 79 | \usepackage[greek,english]{babel} 80 | \usepackage{xunicode} 81 | \usepackage{letltxmacro} 82 | \newcommand{\argmax}{\operatornamewithlimits{argmax}} 83 | \newcommand{\argmin}{\operatornamewithlimits{argmin}} 84 | \DeclareMathOperator{\col}{col} 85 | \setlength{\parskip}{1.5ex plus0.5ex minus0.5ex} 86 | \setlength{\parindent}{0pt} 87 | 88 | \usepackage{letltxmacro} 89 | % https://tex.stackexchange.com/q/88001/5764 90 | \LetLtxMacro\oldttfamily\ttfamily 91 | \DeclareRobustCommand{\ttfamily}{\oldttfamily\csname ttsize\endcsname} 92 | \newcommand{\setttsize}[1]{\def\ttsize{#1}}% 93 | 94 | \DeclareTextFontCommand{\texttt}{\ttfamily} 95 | 96 | % Enable Unicode characters in `Out` code-blocks within verbatim 97 | \usepackage{pmboxdraw} 98 | 99 | % renew commands % 100 | % Set max figure width to be 80% of text width, for now hardcoded. 101 | \renewcommand{\includegraphics}[1]{\begin{center}\Oldincludegraphics[width=.8\maxwidth]{#1}\end{center}} 102 | \renewcommand \caption [2][]{} % removes captions from all figures 103 | \setlist[itemize]{nosep} 104 | 105 | % using CMU Serif for greek and latin letters in code blocks and Liberation Mono for rest% 106 | \setmonofont{Liberation Mono} 107 | \usepackage[Latin,Greek]{ucharclasses} 108 | \newfontfamily\substitutefont{CMU Serif} 109 | \setTransitionsForGreek{\begingroup\substitutefont}{\endgroup} 110 | ((* endblock packages *)) 111 | 112 | % Colors for the hyperref package 113 | \definecolor{urlcolor}{rgb}{0,.145,.698} 114 | \definecolor{linkcolor}{rgb}{.71,0.21,0.01} 115 | \definecolor{citecolor}{rgb}{.12,.54,.11} 116 | 117 | % ANSI colors 118 | \definecolor{ansi-black}{HTML}{3E424D} 119 | \definecolor{ansi-black-intense}{HTML}{282C36} 120 | \definecolor{ansi-red}{HTML}{E75C58} 121 | \definecolor{ansi-red-intense}{HTML}{B22B31} 122 | \definecolor{ansi-green}{HTML}{00A250} 123 | \definecolor{ansi-green-intense}{HTML}{007427} 124 | \definecolor{ansi-yellow}{HTML}{DDB62B} 125 | \definecolor{ansi-yellow-intense}{HTML}{B27D12} 126 | \definecolor{ansi-blue}{HTML}{208FFB} 127 | \definecolor{ansi-blue-intense}{HTML}{0065CA} 128 | \definecolor{ansi-magenta}{HTML}{D160C4} 129 | \definecolor{ansi-magenta-intense}{HTML}{A03196} 130 | \definecolor{ansi-cyan}{HTML}{60C6C8} 131 | \definecolor{ansi-cyan-intense}{HTML}{258F8F} 132 | \definecolor{ansi-white}{HTML}{C5C1B4} 133 | \definecolor{ansi-white-intense}{HTML}{A1A6B2} 134 | \definecolor{ansi-default-inverse-fg}{HTML}{FFFFFF} 135 | \definecolor{ansi-default-inverse-bg}{HTML}{000000} 136 | 137 | 138 | % commands and environments needed by pandoc snippets 139 | % extracted from the output of `pandoc -s` 140 | \providecommand{\tightlist}{% 141 | \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} 142 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} 143 | % Add ',fontsize=\small' for more characters per line 144 | \newenvironment{Shaded}{}{} 145 | \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} 146 | \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} 147 | \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 148 | \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 149 | \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 150 | \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 151 | \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 152 | \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} 153 | \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} 154 | \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} 155 | \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} 156 | \newcommand{\RegionMarkerTok}[1]{{#1}} 157 | \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} 158 | \newcommand{\NormalTok}[1]{{#1}} 159 | 160 | % Additional commands for more recent versions of Pandoc 161 | \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{{#1}}} 162 | \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 163 | \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 164 | \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{{#1}}} 165 | \newcommand{\ImportTok}[1]{{#1}} 166 | \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{{#1}}}} 167 | \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 168 | \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 169 | \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{{#1}}} 170 | \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} 171 | \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{{#1}}} 172 | \newcommand{\BuiltInTok}[1]{{#1}} 173 | \newcommand{\ExtensionTok}[1]{{#1}} 174 | \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{{#1}}} 175 | \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{{#1}}} 176 | \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 177 | \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 178 | 179 | 180 | % Define a nice break command that doesn't care if a line doesn't already 181 | % exist. 182 | \def\br{\hspace*{\fill} \\* } 183 | % Math Jax compatibility definitions 184 | \def\gt{>} 185 | \def\lt{<} 186 | \let\Oldtex\TeX 187 | \let\Oldlatex\LaTeX 188 | \renewcommand{\TeX}{\textrm{\Oldtex}} 189 | \renewcommand{\LaTeX}{\textrm{\Oldlatex} 190 | 191 | %=============================================================================== 192 | % Title Page 193 | %=============================================================================== 194 | 195 | ((* block maketitle *)) 196 | \setttsize{\footnotesize} 197 | 198 | \title{((( nb.metadata.get("latex_metadata", {}).get("title", "") | escape_latex )))} 199 | 200 | ((*- if nb.metadata.get("latex_metadata", {}).get("author", ""): -*)) 201 | \author{((( nb.metadata["latex_metadata"]["author"] )))} 202 | ((*- endif *)) 203 | 204 | ((*- if nb.metadata.get("latex_metadata", {}).get("affiliation", ""): -*)) 205 | \affiliation{((( nb.metadata["latex_metadata"]["affiliation"] )))} 206 | ((*- endif *)) 207 | 208 | \date{\today} 209 | \maketitle 210 | 211 | ((*- if nb.metadata.get("latex_metadata", {}).get("logo", ""): -*)) 212 | \begin{center} 213 | \adjustimage{max size={0.6\linewidth}{0.6\paperheight}}{((( nb.metadata["latex_metadata"]["logo"] )))} 214 | \end{center} 215 | ((*- endif -*)) 216 | 217 | % delete-till-here-book % 218 | ((* endblock maketitle *)) 219 | 220 | 221 | %=============================================================================== 222 | % Input 223 | %=============================================================================== 224 | 225 | % Input cells can be hidden using the "Hide input" and "Hide input all" 226 | % nbextensions (which set the hide_input metadata flags) 227 | 228 | ((* block input scoped *)) 229 | ((( cell.metadata.get("hide_input", "") ))) 230 | ((*- if cell.metadata.hide_input or nb.metadata.hide_input or cell.metadata.get("hide_input", ""): -*)) 231 | ((*- else -*)) 232 | ((( custom_add_prompt(cell.source | wrap_text(88) | highlight_code(strip_verbatim=True), cell, 'In ', 'incolor', 'plain') ))) 233 | ((*- endif *)) 234 | ((* endblock input *)) 235 | 236 | 237 | %=============================================================================== 238 | % Output 239 | %=============================================================================== 240 | 241 | ((* block output_group -*)) 242 | ((*- if cell.metadata.hide_output: -*)) 243 | ((*- else -*)) 244 | ((( super() ))) 245 | ((*- endif -*)) 246 | ((* endblock output_group *)) 247 | 248 | ((* block execute_result scoped *)) 249 | ((*- for type in output.data | filter_data_type -*)) 250 | ((*- if type in ['text/plain']*)) 251 | ((( custom_add_prompt(output.data['text/plain'] | wrap_text(88) | escape_latex | ansi2latex, cell, 'Out', 'outcolor', 'plain') ))) 252 | ((*- elif type in ['text/latex']*)) 253 | ((( custom_add_prompt(output.data['text/latex'] | wrap_text(88) | ansi2latex, cell, 'Out', 'outcolor', 'latex') ))) 254 | ((* else -*)) 255 | ((( custom_add_prompt( '' | wrap_text(88)| escape_latex | ansi2latex, cell, 'Out', 'outcolor', 'plain') ))) 256 | ((*- endif -*)) 257 | ((*- endfor -*)) 258 | ((* endblock execute_result *)) 259 | 260 | % Display stream ouput with coloring 261 | ((* block stream *)) 262 | \begin{Verbatim}[commandchars=\\\{\}, fontsize=\footnotesize] 263 | ((( output.text | wrap_text(86) | escape_latex | ansi2latex ))) 264 | \end{Verbatim} 265 | %((* endblock stream *)) 266 | 267 | %============================================================================== 268 | % Define macro custom_add_prompt() (derived from add_prompt() macro in style_ipython.tplx) 269 | %============================================================================== 270 | 271 | ((* macro custom_add_prompt(text, cell, prompt, prompt_color, type) -*)) 272 | ((*- if cell.execution_count is defined -*)) 273 | ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*)) 274 | ((*- else -*)) 275 | ((*- set execution_count = "" -*)) 276 | ((*- endif -*)) 277 | ((*- set indention = " " * (execution_count | length + 7) -*)) 278 | ((*- if type == 'plain' -*)) 279 | \begin{Verbatim}[commandchars=\\\{\}, fontsize=\small, xleftmargin=-3.9em] 280 | ((( text.replace('$$','').replace('$\\',"\\(\\").replace('$','\)') | add_prompts(first='{\color{' ~ prompt_color ~ '}' ~ prompt ~ '[{\\color{' ~ prompt_color ~ '}' ~ execution_count ~ '}]:} ', cont=indention) ))) 281 | \end{Verbatim} 282 | ((*- else -*)) 283 | \begin{lstlisting}[mathescape, basicstyle=\small\ttfamily\color{black}, keywordstyle={\color{red}}, xleftmargin=-4.8em] 284 | ((( text | add_prompts(first='<@\\textcolor{red}{' ~ prompt ~ '[' ~ execution_count ~ ']: }@>', cont=indention) ))) 285 | \end{lstlisting} 286 | ((*- endif -*)) 287 | ((*- endmacro *)) 288 | 289 | %============================================================================== 290 | % Support Macros 291 | %============================================================================== 292 | 293 | % Name: draw_prompt 294 | % Purpose: Renders an output/input prompt 295 | ((* macro draw_prompt(cell, prompt, prompt_color, extra_space) -*)) 296 | ((*- if cell.execution_count is defined -*)) 297 | ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*)) 298 | ((*- else -*))((*- set execution_count = " " -*))((*- endif *)) 299 | 300 | ((*- if (resources.global_content_filter.include_output_prompt and prompt == 'Out') 301 | or (resources.global_content_filter.include_input_prompt and prompt == 'In' ) *)) 302 | \prompt{(((prompt)))}{(((prompt_color)))}{(((execution_count)))}{(((extra_space)))} 303 | ((*- endif -*)) 304 | ((*- endmacro *)) 305 | 306 | 307 | %============================================================================== 308 | % Bibliography 309 | %============================================================================== 310 | 311 | % Insert citations in markdown as e.g. 312 | % [DevoretS2013] 313 | % requires file references.bib in current directory (or the file set as "bib" in the latex_metadata) 314 | 315 | 316 | ((* block bibliography *)) 317 | % delete-from-here-book % 318 | ((*- if nb.metadata.get("latex_metadata", {}).get("bib_include", ""): -*)) 319 | % Add a bibliography block to the postdoc 320 | \bibliographystyle{plain} 321 | \bibliography{((( nb.metadata.get("latex_metadata", {}).get("bib", "quant-econ") )))} 322 | ((*- endif -*)) 323 | ((* endblock bibliography *)) 324 | -------------------------------------------------------------------------------- /theme/minimal/templates/latex_book.tpl: -------------------------------------------------------------------------------- 1 | ((*- extends 'article.tplx' -*)) 2 | 3 | % See http://blog.juliusschulz.de/blog/ultimate-ipython-notebook#templates 4 | % for some useful tips 5 | 6 | %=============================================================================== 7 | % Document class 8 | %=============================================================================== 9 | 10 | ((* block docclass *)) 11 | \documentclass[a4paper,11pt, twoside]{book} 12 | ((* endblock docclass *)) 13 | 14 | %=============================================================================== 15 | % Packages 16 | %=============================================================================== 17 | 18 | ((* block packages *)) 19 | \usepackage[T1]{fontenc} 20 | \usepackage{graphicx} 21 | \usepackage[breakable]{tcolorbox} 22 | % We will generate all images so they have a width \maxwidth. This means 23 | % that they will get their normal width if they fit onto the page, but 24 | % are scaled down if they would overflow the margins. 25 | \makeatletter 26 | \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth 27 | \else\Gin@nat@width\fi} 28 | \makeatother 29 | \let\Oldincludegraphics\includegraphics 30 | 31 | % propose delete% 32 | % Ensure that by default, figures have no caption (until we provide a 33 | % proper Figure object with a Caption API and a way to capture that 34 | % in the conversion process - todo). 35 | % \usepackage{caption} 36 | % \DeclareCaptionLabelFormat{empty}{} 37 | %\captionsetup{format=empty,aboveskip=0pt,belowskip=0pt} 38 | % end - propose delete% 39 | 40 | % float figure settings% 41 | \usepackage{float} 42 | \floatplacement{figure}{H} % used to force figures for placement in text 43 | 44 | \usepackage{adjustbox} % Used to constrain images to a maximum size 45 | \usepackage{xcolor} % Allow colors to be defined 46 | \usepackage{enumerate} % Needed for markdown enumerations to work 47 | \usepackage{geometry} % Used to adjust the document margins 48 | \usepackage{amsmath} % Equations 49 | \usepackage{amssymb} % Equations 50 | \usepackage{textcomp} % defines textquotesingle 51 | % Hack from http://tex.stackexchange.com/a/47451/13684: 52 | \AtBeginDocument{% 53 | \def\PYZsq{\textquotesingle}% Upright quotes in Pygmentized code 54 | } 55 | \usepackage{upquote} % Upright quotes for verbatim code 56 | \usepackage{eurosym} % defines \euro 57 | \usepackage[mathletters]{ucs} % Extended unicode (utf-8) support 58 | \usepackage[utf8x]{inputenc} % Allow utf-8 characters in the tex document 59 | \usepackage{fancyvrb} % verbatim replacement that allows latex 60 | \usepackage{listings} 61 | \lstset{escapeinside={<@}{@>}} 62 | \usepackage{grffile} % extends the file name processing of package graphics 63 | % to support a larger range 64 | % The hyperref package gives us a pdf with properly built 65 | % internal navigation ('pdf bookmarks' for the table of contents, 66 | % internal cross-reference links, web links for URLs, etc.) 67 | \usepackage{hyperref} 68 | \usepackage{longtable} % longtable support required by pandoc >1.10 69 | \usepackage{booktabs} % table support for pandoc > 1.12.2 70 | \usepackage[inline]{enumitem} % IRkernel/repr support (it uses the enumerate* environment) 71 | \usepackage[normalem]{ulem} % ulem is needed to support strikethroughs (\sout) 72 | % normalem makes italics be italics, not underlines 73 | \usepackage{braket} 74 | \usepackage{mathrsfs} 75 | \usepackage{natbib} 76 | \usepackage[document]{ragged2e} 77 | \usepackage{fontspec, unicode-math} 78 | \usepackage[greek,english]{babel} 79 | \usepackage{xunicode} 80 | \usepackage{letltxmacro} 81 | \newcommand{\argmax}{\operatornamewithlimits{argmax}} 82 | \newcommand{\argmin}{\operatornamewithlimits{argmin}} 83 | \DeclareMathOperator{\col}{col} 84 | \setlength{\parskip}{1.5ex plus0.5ex minus0.5ex} 85 | \setlength{\parindent}{0pt} 86 | 87 | \usepackage{letltxmacro} 88 | % https://tex.stackexchange.com/q/88001/5764 89 | \LetLtxMacro\oldttfamily\ttfamily 90 | \DeclareRobustCommand{\ttfamily}{\oldttfamily\csname ttsize\endcsname} 91 | \newcommand{\setttsize}[1]{\def\ttsize{#1}}% 92 | 93 | \DeclareTextFontCommand{\texttt}{\ttfamily} 94 | 95 | % Enable Unicode characters in `Out` code-blocks within verbatim 96 | \usepackage{pmboxdraw} 97 | 98 | % renew commands % 99 | % Set max figure width to be 80% of text width, for now hardcoded. 100 | \renewcommand{\includegraphics}[1]{\begin{center}\Oldincludegraphics[width=.8\maxwidth]{#1}\end{center}} 101 | \renewcommand \caption [2][]{} % removes captions from all figures 102 | \setlist[itemize]{nosep} 103 | 104 | % using CMU Serif for greek and latin letters in code blocks and Liberation Mono for rest% 105 | \setmonofont{Liberation Mono} 106 | \usepackage[Latin,Greek]{ucharclasses} 107 | \newfontfamily\substitutefont{CMU Serif} 108 | \setTransitionsForGreek{\begingroup\substitutefont}{\endgroup} 109 | ((* endblock packages *)) 110 | 111 | % Colors for the hyperref package 112 | \definecolor{urlcolor}{rgb}{0,.145,.698} 113 | \definecolor{linkcolor}{rgb}{.71,0.21,0.01} 114 | \definecolor{citecolor}{rgb}{.12,.54,.11} 115 | 116 | % ANSI colors 117 | \definecolor{ansi-black}{HTML}{3E424D} 118 | \definecolor{ansi-black-intense}{HTML}{282C36} 119 | \definecolor{ansi-red}{HTML}{E75C58} 120 | \definecolor{ansi-red-intense}{HTML}{B22B31} 121 | \definecolor{ansi-green}{HTML}{00A250} 122 | \definecolor{ansi-green-intense}{HTML}{007427} 123 | \definecolor{ansi-yellow}{HTML}{DDB62B} 124 | \definecolor{ansi-yellow-intense}{HTML}{B27D12} 125 | \definecolor{ansi-blue}{HTML}{208FFB} 126 | \definecolor{ansi-blue-intense}{HTML}{0065CA} 127 | \definecolor{ansi-magenta}{HTML}{D160C4} 128 | \definecolor{ansi-magenta-intense}{HTML}{A03196} 129 | \definecolor{ansi-cyan}{HTML}{60C6C8} 130 | \definecolor{ansi-cyan-intense}{HTML}{258F8F} 131 | \definecolor{ansi-white}{HTML}{C5C1B4} 132 | \definecolor{ansi-white-intense}{HTML}{A1A6B2} 133 | \definecolor{ansi-default-inverse-fg}{HTML}{FFFFFF} 134 | \definecolor{ansi-default-inverse-bg}{HTML}{000000} 135 | 136 | 137 | % commands and environments needed by pandoc snippets 138 | % extracted from the output of `pandoc -s` 139 | \providecommand{\tightlist}{% 140 | \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} 141 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} 142 | % Add ',fontsize=\small' for more characters per line 143 | \newenvironment{Shaded}{}{} 144 | \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} 145 | \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} 146 | \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 147 | \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 148 | \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 149 | \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 150 | \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 151 | \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} 152 | \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} 153 | \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} 154 | \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} 155 | \newcommand{\RegionMarkerTok}[1]{{#1}} 156 | \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} 157 | \newcommand{\NormalTok}[1]{{#1}} 158 | 159 | % Additional commands for more recent versions of Pandoc 160 | \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{{#1}}} 161 | \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 162 | \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 163 | \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{{#1}}} 164 | \newcommand{\ImportTok}[1]{{#1}} 165 | \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{{#1}}}} 166 | \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 167 | \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 168 | \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{{#1}}} 169 | \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} 170 | \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{{#1}}} 171 | \newcommand{\BuiltInTok}[1]{{#1}} 172 | \newcommand{\ExtensionTok}[1]{{#1}} 173 | \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{{#1}}} 174 | \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{{#1}}} 175 | \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 176 | \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{{#1}}}}} 177 | 178 | 179 | % Define a nice break command that doesn't care if a line doesn't already 180 | % exist. 181 | \def\br{\hspace*{\fill} \\* } 182 | % Math Jax compatibility definitions 183 | \def\gt{>} 184 | \def\lt{<} 185 | \let\Oldtex\TeX 186 | \let\Oldlatex\LaTeX 187 | \renewcommand{\TeX}{\textrm{\Oldtex}} 188 | \renewcommand{\LaTeX}{\textrm{\Oldlatex} 189 | 190 | %=============================================================================== 191 | % Title Page 192 | %=============================================================================== 193 | 194 | ((* block maketitle *)) 195 | \setttsize{\footnotesize} 196 | 197 | ((*- if nb.metadata.get("latex_metadata", {}).get("jupyter_pdf_book_title", ""): -*)) 198 | \title{\Huge \textbf{((( nb.metadata["latex_metadata"]["jupyter_pdf_book_title"] )))}} 199 | ((*- endif *)) 200 | 201 | ((*- if nb.metadata.get("latex_metadata", {}).get("author", ""): -*)) 202 | \author{\textsc{((( nb.metadata["latex_metadata"]["author"] )))}} 203 | ((*- endif *)) 204 | 205 | ((*- if nb.metadata.get("latex_metadata", {}).get("affiliation", ""): -*)) 206 | \affiliation{((( nb.metadata["latex_metadata"]["affiliation"] )))} 207 | ((*- endif *)) 208 | 209 | \date{\today} 210 | \maketitle 211 | 212 | \setcounter{tocdepth}{0} 213 | \tableofcontents 214 | 215 | 216 | \parskip 0.09in 217 | 218 | \mainmatter 219 | 220 | ((* endblock maketitle *)) 221 | 222 | %=============================================================================== 223 | % Input 224 | %=============================================================================== 225 | 226 | % Input cells can be hidden using the "Hide input" and "Hide input all" 227 | % nbextensions (which set the hide_input metadata flags) 228 | 229 | ((* block input scoped *)) 230 | ((( cell.metadata.get("hide_input", "") ))) 231 | ((*- if cell.metadata.hide_input or nb.metadata.hide_input or cell.metadata.get("hide_input", ""): -*)) 232 | ((*- else -*)) 233 | ((( custom_add_prompt(cell.source | wrap_text(88) | highlight_code(strip_verbatim=True), cell, 'In ', 'incolor', 'plain') ))) 234 | ((*- endif *)) 235 | ((* endblock input *)) 236 | 237 | 238 | %=============================================================================== 239 | % Output 240 | %=============================================================================== 241 | 242 | ((* block output_group -*)) 243 | ((*- if cell.metadata.hide_output: -*)) 244 | ((*- else -*)) 245 | ((( super() ))) 246 | ((*- endif -*)) 247 | ((* endblock output_group *)) 248 | 249 | ((* block execute_result scoped *)) 250 | ((*- for type in output.data | filter_data_type -*)) 251 | ((*- if type in ['text/plain']*)) 252 | ((( custom_add_prompt(output.data['text/plain'] | wrap_text(88) | escape_latex | ansi2latex, cell, 'Out', 'outcolor', 'plain') ))) 253 | ((*- elif type in ['text/latex']*)) 254 | ((( custom_add_prompt(output.data['text/latex'] | wrap_text(88) | ansi2latex, cell, 'Out', 'outcolor', 'latex') ))) 255 | ((* else -*)) 256 | ((( custom_add_prompt( '' | wrap_text(88)| escape_latex | ansi2latex, cell, 'Out', 'outcolor', 'plain') ))) 257 | ((*- endif -*)) 258 | ((*- endfor -*)) 259 | ((* endblock execute_result *)) 260 | 261 | % Display stream ouput with coloring 262 | ((* block stream *)) 263 | \begin{Verbatim}[commandchars=\\\{\}, fontsize=\footnotesize] 264 | ((( output.text | wrap_text(86) | escape_latex | ansi2latex ))) 265 | \end{Verbatim} 266 | %((* endblock stream *)) 267 | 268 | %============================================================================== 269 | % Define macro custom_add_prompt() (derived from add_prompt() macro in style_ipython.tplx) 270 | %============================================================================== 271 | 272 | ((* macro custom_add_prompt(text, cell, prompt, prompt_color, type) -*)) 273 | ((*- if cell.execution_count is defined -*)) 274 | ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*)) 275 | ((*- else -*)) 276 | ((*- set execution_count = "" -*)) 277 | ((*- endif -*)) 278 | ((*- set indention = " " * (execution_count | length + 7) -*)) 279 | ((*- if type == 'plain' -*)) 280 | \begin{Verbatim}[commandchars=\\\{\}, fontsize=\small, xleftmargin=-3.9em] 281 | ((( text.replace('$$','').replace('$\\',"\\(\\").replace('$','\)') | add_prompts(first='{\color{' ~ prompt_color ~ '}' ~ prompt ~ '[{\\color{' ~ prompt_color ~ '}' ~ execution_count ~ '}]:} ', cont=indention) ))) 282 | \end{Verbatim} 283 | ((*- else -*)) 284 | \begin{lstlisting}[mathescape, basicstyle=\small\ttfamily\color{black}, xleftmargin=-3.9em] 285 | ((( text | add_prompts(first='<@\\textcolor{red}{' ~ prompt ~ '[' ~ execution_count ~ ']: }@>', cont=indention) ))) 286 | \end{lstlisting} 287 | ((*- endif -*)) 288 | ((*- endmacro *)) 289 | 290 | %============================================================================== 291 | % Support Macros 292 | %============================================================================== 293 | 294 | % Name: draw_prompt 295 | % Purpose: Renders an output/input prompt 296 | ((* macro draw_prompt(cell, prompt, prompt_color, extra_space) -*)) 297 | ((*- if cell.execution_count is defined -*)) 298 | ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*)) 299 | ((*- else -*))((*- set execution_count = " " -*))((*- endif *)) 300 | 301 | ((*- if (resources.global_content_filter.include_output_prompt and prompt == 'Out') 302 | or (resources.global_content_filter.include_input_prompt and prompt == 'In' ) *)) 303 | \prompt{(((prompt)))}{(((prompt_color)))}{(((execution_count)))}{(((extra_space)))} 304 | ((*- endif -*)) 305 | ((*- endmacro *)) 306 | 307 | 308 | %============================================================================== 309 | % Bibliography 310 | %============================================================================== 311 | 312 | % Insert citations in markdown as e.g. 313 | % [DevoretS2013] 314 | % requires file references.bib in current directory (or the file set as "bib" in the latex_metadata) 315 | 316 | 317 | ((* block bibliography *)) 318 | % Add a bibliography block to the postdoc 319 | ((* endblock bibliography *)) 320 | --------------------------------------------------------------------------------