From 444ca698bb12fc98713da48311570186d0e8f76b Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Wed, 19 Jun 2019 13:58:24 -0700 Subject: [PATCH 1/7] updating binder environment and link --- README.md | 2 +- binder/postBuild | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f69a26c5f..ec6b12368 100755 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The languages that are currently supported by Jupytext are: Julia, Python, R, Ba [![Introducing Jupytext](https://img.shields.io/badge/TDS-Introducing%20Jupytext-blue.svg)](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) [![PyParis](https://img.shields.io/badge/YouTube-PyParis-red.svg)](https://www.youtube.com/watch?v=y-VEZenk824) -[![Binder](https://img.shields.io/badge/Binder-Try%20it!-blue.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/master?filepath=demo) +[![Binder](https://img.shields.io/badge/Binder-Try%20it!-blue.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo) Looking for a demo? - Read the original [announcement](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) in Towards Data Science, diff --git a/binder/postBuild b/binder/postBuild index b1c072ce1..97ef8b235 100644 --- a/binder/postBuild +++ b/binder/postBuild @@ -3,3 +3,8 @@ python -m bash_kernel.install # Trust our notebook jupyter trust demo/World\ population.ipynb + +# Set up extensions for JupyterLab and Notebook +jupyter labextension install jupyterlab-jupytext +jupyter nbextension install --py jupytext --user +jupyter nbextension enable --py jupytext --user From a08c2c0d4012f7d98d1a35083f2cecba65aab0d7 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Wed, 19 Jun 2019 14:29:40 -0700 Subject: [PATCH 2/7] adding binder demo --- README.md | 2 +- demo/get_started.ipynb | 119 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 demo/get_started.ipynb diff --git a/README.md b/README.md index ec6b12368..9218586fe 100755 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The languages that are currently supported by Jupytext are: Julia, Python, R, Ba Looking for a demo? - Read the original [announcement](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) in Towards Data Science, - Watch the [PyParis talk](https://github.com/mwouts/jupytext_pyparis_2018/blob/master/README.md), -- or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?filepath=demo)! +- or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?filepath=demo/get_started.ipynb)! ## Installation diff --git a/demo/get_started.ipynb b/demo/get_started.ipynb new file mode 100644 index 000000000..d7bdb8348 --- /dev/null +++ b/demo/get_started.ipynb @@ -0,0 +1,119 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting started with Jupytext\n", + "\n", + "This small notebook shows you how to activate Jupytext in the JupyterLab\n", + "environment. We'll show you a few things that you can do with Jupytext and\n", + "a bit of what happens under the hood.\n", + "\n", + "**Note: to run this notebook locally, you need to first follow the Jupytext\n", + "installation instructions and activate the JupyterLab plugin. If you're on\n", + "Binder, it should already work.**\n", + "\n", + "## Enabling Jupytext in a new notebook\n", + "\n", + "This notebook is brand new - it hasn't had any special extra metadata added\n", + "to it. \n", + "\n", + "If we want Jupytext to save files in multiple formats automatically,\n", + "we can use the JupyterLab **command palette** to do so.\n", + "\n", + "* Click on the little 🎨 icon to the left\n", + "* Then type **`Jupytext`**. You should see a number of commands come up. Each\n", + " one tells Jupytext to save the notebook in a different\n", + " file format automatically.\n", + "* Select **Pair notebook with Markdown**\n", + "\n", + "That's it! If you have Jupytext installed, it will now save your notebook in\n", + "markdown format automatically when you save this `.ipynb` file.\n", + "\n", + "After you've done this, save the notebook. You should now see a new file called\n", + "**`get_started.md`** in the same directory as this notebook.\n", + "\n", + "## How does Jupytext know to do this?\n", + "\n", + "Jupytext uses notebook-level metadata to keep track of what languages are paired\n", + "with a notebook. Below we'll print the metadata of this notebook so you can see\n", + "what the Jupytext metadata looks like." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import nbformat as nbf\n", + "from IPython.display import JSON\n", + "notebook = nbf.read('./get_started.ipynb', nbf.NO_CONVERT)\n", + "JSON(notebook['metadata'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you select different languages from the command palette (following the instructions\n", + "above) and save the notebook, you'll see this metadata change." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## That's it!\n", + "\n", + "Play around with different kinds of code and outputs to see how each is\n", + "converted into its corresponding text format. Here's a little Python code\n", + "to get you started:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "plt.scatter(*np.random.randn(2, 100), c=np.random.randn(100), s=np.random.rand(100)*100)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Experiment with other notebooks\n", + "\n", + "There are several other demo notebooks for you to explore Jupytext's functionality,\n", + "try them out!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 22575475bb4ca10e304b6d4344d1ae140825228d Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Wed, 19 Jun 2019 15:10:04 -0700 Subject: [PATCH 3/7] adding binder links --- README.md | 4 ++-- docs/introduction.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9218586fe..8fd8f3862 100755 --- a/README.md +++ b/README.md @@ -25,12 +25,12 @@ The languages that are currently supported by Jupytext are: Julia, Python, R, Ba [![Introducing Jupytext](https://img.shields.io/badge/TDS-Introducing%20Jupytext-blue.svg)](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) [![PyParis](https://img.shields.io/badge/YouTube-PyParis-red.svg)](https://www.youtube.com/watch?v=y-VEZenk824) -[![Binder](https://img.shields.io/badge/Binder-Try%20it!-blue.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo) +[![Binder](https://img.shields.io/badge/Binder-Try%20it!-blue.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo/get_started.ipynb) Looking for a demo? - Read the original [announcement](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) in Towards Data Science, - Watch the [PyParis talk](https://github.com/mwouts/jupytext_pyparis_2018/blob/master/README.md), -- or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?filepath=demo/get_started.ipynb)! +- or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo/get_started.ipynb)! ## Installation diff --git a/docs/introduction.md b/docs/introduction.md index 6f00b9f7f..09fe92d97 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -38,12 +38,12 @@ In short: the Markdown representation of notebooks fits well the notebooks that [![](https://img.shields.io/badge/TDS-Introducing%20Jupytext-blue.svg)](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) [![](https://img.shields.io/badge/YouTube-PyParis-red.svg)](https://www.youtube.com/watch?v=y-VEZenk824) -[![](https://img.shields.io/badge/Binder-Try%20it!-blue.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/master?filepath=demo) +[![](https://img.shields.io/badge/Binder-Try%20it!-blue.svg)](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo/get_started.ipynb) Looking for a demo? - Read the original [announcement](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) in Towards Data Science, - Watch the [PyParis talk](https://github.com/mwouts/jupytext_pyparis_2018/blob/master/README.md), -- or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?filepath=demo)! +- or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo/get_started.ipynb)! ## Want to contribute? From 7e094ba538aa0fec42a5975653843d1707e9a833 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Wed, 19 Jun 2019 17:45:38 -0700 Subject: [PATCH 4/7] removing extra demo files and keeping markdown --- .gitignore | 14 +- binder/postBuild | 6 +- demo/Matplotlib example.py | 227 ------------------ ...d Jupyter notebook and python script.ipynb | 126 ---------- ...ired Jupyter notebook and python script.py | 49 ---- demo/World population.Rmd | 113 --------- demo/World population.lgt.py | 95 -------- demo/World population.md | 113 --------- demo/World population.pandoc.md | 155 ------------ demo/World population.pct.py | 111 --------- demo/World population.spx.py | 103 -------- demo/get_started.ipynb | 119 --------- demo/get_started.md | 81 +++++++ demo/sample_python_script.py | 33 --- 14 files changed, 98 insertions(+), 1247 deletions(-) delete mode 100644 demo/Matplotlib example.py delete mode 100644 demo/Paired Jupyter notebook and python script.ipynb delete mode 100644 demo/Paired Jupyter notebook and python script.py delete mode 100644 demo/World population.Rmd delete mode 100644 demo/World population.lgt.py delete mode 100644 demo/World population.md delete mode 100644 demo/World population.pandoc.md delete mode 100644 demo/World population.pct.py delete mode 100644 demo/World population.spx.py delete mode 100644 demo/get_started.ipynb create mode 100644 demo/get_started.md delete mode 100644 demo/sample_python_script.py diff --git a/.gitignore b/.gitignore index b0b2aafb4..93c5fd0db 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,16 @@ future *.pyc gits* .ipynb_checkpoints -docs/_build \ No newline at end of file +docs/_build + +# Will be created by postBuild +demo/get_started.ipynb + +# Files that will be created by saving the World population notebook +demo/Paired Jupyter notebook and python script.py +demo/World population.Rmd +demo/World population.lgt.py +demo/World population.md +demo/World population.pandoc.md +demo/World population.pct.py +demo/World population.spx.py \ No newline at end of file diff --git a/binder/postBuild b/binder/postBuild index 97ef8b235..45cf1a493 100644 --- a/binder/postBuild +++ b/binder/postBuild @@ -6,5 +6,7 @@ jupyter trust demo/World\ population.ipynb # Set up extensions for JupyterLab and Notebook jupyter labextension install jupyterlab-jupytext -jupyter nbextension install --py jupytext --user -jupyter nbextension enable --py jupytext --user + +# Create the notebook for our jupytext demo +jupytext demo/get_started.md --to ipynb --update-metadata '{"jupytext":null}' +rm demo/get_started.md diff --git a/demo/Matplotlib example.py b/demo/Matplotlib example.py deleted file mode 100644 index aa07f338b..000000000 --- a/demo/Matplotlib example.py +++ /dev/null @@ -1,227 +0,0 @@ -# From https://matplotlib.org/examples/api/filled_step.html - -""" -========================= -Hatch-filled histograms -========================= - -Hatching capabilities for plotting histograms. -From https://matplotlib.org/gallery/api/filled_step.html -""" - -import itertools -from collections import OrderedDict -from functools import partial - -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.ticker as mticker -from cycler import cycler -from six.moves import zip - - -def filled_hist(ax, edges, values, bottoms=None, orientation='v', - **kwargs): - """ - Draw a histogram as a stepped patch. - - Extra kwargs are passed through to `fill_between` - - Parameters - ---------- - ax : Axes - The axes to plot to - - edges : array - A length n+1 array giving the left edges of each bin and the - right edge of the last bin. - - values : array - A length n array of bin counts or values - - bottoms : scalar or array, optional - A length n array of the bottom of the bars. If None, zero is used. - - orientation : {'v', 'h'} - Orientation of the histogram. 'v' (default) has - the bars increasing in the positive y-direction. - - Returns - ------- - ret : PolyCollection - Artist added to the Axes - """ - print(orientation) - if orientation not in set('hv'): - raise ValueError("orientation must be in {{'h', 'v'}} " - "not {o}".format(o=orientation)) - - kwargs.setdefault('step', 'post') - edges = np.asarray(edges) - values = np.asarray(values) - if len(edges) - 1 != len(values): - raise ValueError('Must provide one more bin edge than value not: ' - 'len(edges): {lb} len(values): {lv}'.format( - lb=len(edges), lv=len(values))) - - if bottoms is None: - bottoms = np.zeros_like(values) - if np.isscalar(bottoms): - bottoms = np.ones_like(values) * bottoms - - values = np.r_[values, values[-1]] - bottoms = np.r_[bottoms, bottoms[-1]] - if orientation == 'h': - return ax.fill_betweenx(edges, values, bottoms, - **kwargs) - elif orientation == 'v': - return ax.fill_between(edges, values, bottoms, - **kwargs) - else: - raise AssertionError("you should never be here") - - -def stack_hist(ax, stacked_data, sty_cycle, bottoms=None, - hist_func=None, labels=None, - plot_func=None, plot_kwargs=None): - """ - ax : axes.Axes - The axes to add artists too - - stacked_data : array or Mapping - A (N, M) shaped array. The first dimension will be iterated over to - compute histograms row-wise - - sty_cycle : Cycler or operable of dict - Style to apply to each set - - bottoms : array, optional - The initial positions of the bottoms, defaults to 0 - - hist_func : callable, optional - Must have signature `bin_vals, bin_edges = f(data)`. - `bin_edges` expected to be one longer than `bin_vals` - - labels : list of str, optional - The label for each set. - - If not given and stacked data is an array defaults to 'default set {n}' - - If stacked_data is a mapping, and labels is None, default to the keys - (which may come out in a random order). - - If stacked_data is a mapping and labels is given then only - the columns listed by be plotted. - - plot_func : callable, optional - Function to call to draw the histogram must have signature: - - ret = plot_func(ax, edges, top, bottoms=bottoms, - label=label, **kwargs) - - plot_kwargs : dict, optional - Any extra kwargs to pass through to the plotting function. This - will be the same for all calls to the plotting function and will - over-ride the values in cycle. - - Returns - ------- - arts : dict - Dictionary of artists keyed on their labels - """ - # deal with default binning function - if hist_func is None: - hist_func = np.histogram - - # deal with default plotting function - if plot_func is None: - plot_func = filled_hist - - # deal with default - if plot_kwargs is None: - plot_kwargs = {} - print(plot_kwargs) - try: - l_keys = stacked_data.keys() - label_data = True - if labels is None: - labels = l_keys - - except AttributeError: - label_data = False - if labels is None: - labels = itertools.repeat(None) - - if label_data: - loop_iter = enumerate((stacked_data[lab], lab, s) for lab, s in - zip(labels, sty_cycle)) - else: - loop_iter = enumerate(zip(stacked_data, labels, sty_cycle)) - - arts = {} - for j, (data, label, sty) in loop_iter: - if label is None: - label = 'dflt set {n}'.format(n=j) - label = sty.pop('label', label) - vals, edges = hist_func(data) - if bottoms is None: - bottoms = np.zeros_like(vals) - top = bottoms + vals - print(sty) - sty.update(plot_kwargs) - print(sty) - ret = plot_func(ax, edges, top, bottoms=bottoms, - label=label, **sty) - bottoms = top - arts[label] = ret - ax.legend(fontsize=10) - return arts - - -# set up histogram function to fixed bins -edges = np.linspace(-3, 3, 20, endpoint=True) -hist_func = partial(np.histogram, bins=edges) - -# set up style cycles -color_cycle = cycler(facecolor=plt.rcParams['axes.prop_cycle'][:4]) -label_cycle = cycler('label', ['set {n}'.format(n=n) for n in range(4)]) -hatch_cycle = cycler('hatch', ['/', '*', '+', '|']) - -# Fixing random state for reproducibility -np.random.seed(19680801) - -stack_data = np.random.randn(4, 12250) -dict_data = OrderedDict(zip((c['label'] for c in label_cycle), stack_data)) - -############################################################################### -# Work with plain arrays - -fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5), tight_layout=True) -arts = stack_hist(ax1, stack_data, color_cycle + label_cycle + hatch_cycle, - hist_func=hist_func) - -arts = stack_hist(ax2, stack_data, color_cycle, - hist_func=hist_func, - plot_kwargs=dict(edgecolor='w', orientation='h')) -ax1.set_ylabel('counts') -ax1.set_xlabel('x') -ax2.set_xlabel('counts') -ax2.set_ylabel('x') - -############################################################################### -# Work with labeled data - -fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5), - tight_layout=True, sharey=True) - -arts = stack_hist(ax1, dict_data, color_cycle + hatch_cycle, - hist_func=hist_func) - -arts = stack_hist(ax2, dict_data, color_cycle + hatch_cycle, - hist_func=hist_func, labels=['set 0', 'set 3']) -ax1.xaxis.set_major_locator(mticker.MaxNLocator(5)) -ax1.set_xlabel('counts') -ax1.set_ylabel('x') -ax2.set_ylabel('x') - -plt.show() diff --git a/demo/Paired Jupyter notebook and python script.ipynb b/demo/Paired Jupyter notebook and python script.ipynb deleted file mode 100644 index 02089cd77..000000000 --- a/demo/Paired Jupyter notebook and python script.ipynb +++ /dev/null @@ -1,126 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is a notebook that you can use to experiment with the jupytext package.\n", - "\n", - "Proposed experimentations are\n", - "1. Open this Jupyter notebook (extension .ipynb) in Jupyter\n", - "2. Open the corresponding '.py' file. That is, copy the url for the notebook, that looks like\n", - "```\n", - "https://hub.mybinder.org/user/mwouts-jupytext-g7315gce/notebooks/demo/Sample%20notebook%20with%20python%20representation.ipynb\n", - "```\n", - "replace `/notebooks/` with `/edit/`, and change the extension from `ipynb` to `py`, to get an url like\n", - "```\n", - "https://hub.mybinder.org/user/mwouts-jupytext-g7315gce/edit/demo/Sample%20notebook%20with%20python%20representation.py\n", - "```\n", - "3. Modify the notebook in Jupyter. Save. Refresh the python file in the editor, and observe the changes.\n", - "4. Now, modify the python file, save, and refresh the Jupyter notebook. Observe how inputs were updated, outputs preserved when possible, and kernel was left unchanged.\n", - "5. Browse the github repo using Jupyter in binder, and open arbitrary python files as notebooks. Run them when applicable." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5,1,'About as simple as it gets, folks')" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYwAAAEWCAYAAAB1xKBvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzs3Xl8VOW9+PHPN/u+L0AIhIQAgiJLhIRFxQ2sVrEraG+1m7Vqe7svt7/a2/Xut73ertpar9ZqrbutSl0QQQgQRJA9G5AAIRtkJfv398c5o0PMMoHMnFme9+s1r8yc9Tsnz8wz51lFVTEMwzCM0YQ5HYBhGIYRGEyGYRiGYXjEZBiGYRiGR0yGYRiGYXjEZBiGYRiGR0yGYRiGYXjEZBjGu0TkQRH5sdNxeIOI3CIif/fSsR29biKyXEQOOnX+cyWWP4jIKRHZ5sH2KiLT7edBm1b9mckwQpCIvG5/SKN9dL48+8Me4YvzDUVVH1HVa5w6vzep6kZVnel6LSKHReQqb5xLRC4XkdpxOtwy4GpgsqouGqdjGl5kMowQIyJ5wHJAgRscDcYIdVOBw6ra4XQghmdMhhF6PgmUAg8Ctw6xPkNEXhaRNhHZICJTXStEZImIbBeRFvvvErd1Z/2qFZF/FpE/2i/fsP+eFpF2ESkZfFIRWSQiW0TktIicEJFfiEiUvU5E5GciUm+fe7eIXDjUmxOR20Skyo6/WkRucVu+yW07FZE7RaTc3vZHIlJgx9AqIo+7nf9yEakVkX8SkUb7vd4y3AUWketF5G37vWwWkbkjbPs/IlJjn3OHiCwfdE3K7HUnReS/hznGu7/6ReRhYArwvH2tvznMPt+0r/NxEfnsoOKeaBH5TxE5ap/3NyISKyLxwIvAJPvY7SIyydM4B53/M8DvgBL7OD+wl39ORCpEpFlEnhORSR4cK1FE1ovIvXZa+YCI7LP/r8dE5OujHcPwkKqaRwg9gArgTmAh0Atku617EGgDLgWigf8BNtnr0oBTwD8AEcBa+3W6vf4wcJXbsf4Z+KP9PA/rjiZihLgWAsX2sfOA/cCX7XUrgR1ACiDABcDEIY4RD7QCM+3XE4E59vPbXO/Ffq3Ac0ASMAfoBl4F8oFkYB9wq73t5UAf8N/2dbkM6HA7z4PAj+3nC4B6YDEQjpUpHwaih3nfnwDS7ff9NaAOiLHXbQH+wX6eABQPc4zLgVq312f9L4bYfpV9njlAHPCwfT2m2+t/bl+bNCAReB74l6HONZY4h4hj8P/kCqDRvobRwP8Cbwz6n7lifBD4sX3ttrmuv73uBLDcfp4KLHD6cxcsD3OHEUJEZBlWMcDjqroDqARuHrTZ31T1DVXtBr6L9QswF7gOKFfVh1W1T1UfBQ4AHxyP2FR1h6qW2sc+DPwW64sZrIwtEZgFiKruV9UTwxxqALhQRGJV9YSq7h3htP+mqq32NnuAv6tqlaq2YP2Snj9o+++pareqbgD+BnxsiGN+Dvitqm5V1X5V/T+szKh4mPf9R1Vtst/3f2F9UbrqI3qB6SKSoartqlo6wnsZi48Bf1DVvaraCfzAtUJExH4PX1HVZlVtA34KrBnheOMV5y3AA6r6lp3+voOV/vKG2X4SsAH4i6r+v0HxzBaRJFU9papvnWM8xiAmwwgtt2J9KTbar//E+4ulalxPVLUdaMb6YE4Cjgza9giQMx6BicgMEfmriNSJSCvWl1SGHcdrwC+AXwInReQ+EUkafAy1ysI/DtwBnBCRv4nIrBFOe9Lt+ZkhXie4vT6lZ5e1H8G6JoNNBb5mF0edFpHTQO4w2yIiXxOR/XZR22msu5sMe/VngBnAAbGKAK8f4b2MxSTc/s+Dnmdi3XXscIv/JXv5cMYrzrPSmJ3+mhg+jV0HxAK/GbT8w8AHgCNiFau+rwjUODcmwwgRIhKL9cvyMvtLuQ74CnCxiFzstmmu2z4JWMUSx+3HVM42BThmP+/A+qJxmeD23JMhkX+NdcdSqKpJwD9hFT9ZB1C9V1UXYhWjzAC+MdRBVHWdql6NVRx1ALjfg3N7ItUuw3eZgnVNBqsBfqKqKW6POPuO7Cx2fcW3sP4vqaqaArRgv29VLVfVtUAW8G/AE4NiGM5o1/sEMNntda7b80aszHKOW/zJqurKPN937POIc7Cz0ph9jHTeS2OD3Y+Vmb3gfj5V3a6qN9rxPAM8fg6xGEMwGUboWA30A7OBefbjAmAjVkW4ywdEZJld4fsjYKuq1gAvADNE5GYRiRCRj9vH+qu939vAGhGJFJEi4CNux2zAKirKHyG+RKz6h3b7ruALrhUicomILBaRSKyMqct+L2cRkWwRucH+8ugG2ofa7jz8QESi7C/664G/DLHN/cAddrwiIvEicp2IJA6xbSJW3UgDECEi92DVqbjezydEJFNVB4DT9mJP3s9JRr7WjwOfEpELRCQOuMe1wj7X/cDPRCTLjiNHRFa6HTtdRJI9iVOsBgK3eRAzWHe8nxKReWI1+f4pVvo7PMI+dwMHgb/aFfNRYvW5SVbVXqw0NZ5pIKSZDCN03IpVbn1UVetcD6yinlvkvT4SfwK+j1UUtRCrXBlVbcL6kvwaVjHBN4Hr3Yq3vgcUYFWE/8A+Dva+ncBPgDftYo6hyvO/jlWf0ob1hfVnt3VJ9rJTWEUWTcB/DnGMMDu+43b8l2FV8I+HOvv8x4FHgDtU9cDgjVS1DKsO4Bf29hVYlbtDWYdVV3II6311cXbx0Cpgr4i0YzVAWKOqXR7E+i/A/7Ov9ftaCKnqi8C9wHo7vi32qm7777fs5aV28eAr2PUq9nt+FKiyjz9puDjtHx3pWK3yRqWqr2Kloyex7oIKGLnuBFVV4Has6/YsEIPVMOOwHfsdWA0LjHEg1vU2DGM4InI5VouvyaNtG4hE5AKsSv9oVe0bx+MuA+6yi6uMIGDuMAwjBInITXbxTSpWvcPz45lZAKjqJpNZBBeTYRhGaPo8Vt1JJVYZ/xdG3twwTJGUYRiG4SFzh2EYhmF4xLHRQ70hIyND8/LynA7DMAwjYOzYsaNRVUfqmPmuoMow8vLyKCsrczoMwzCMgCEig0dwGJYpkjIMwzA8YjIMwzAMwyMmwzAMwzA8YjIMwzAMwyMmwzAMwzA84rUMQ0Ry7WkT94vIXhH5xyG2EbGmVawQa9rNBW7rbhVr+sxyERlqKlHDMAzDh7zZrLYP+JqqvmUP7bxDRF5W1X1u21wLFNqPxVhzIiwWkTSsEVOLsMbf3yEiz6nqKS/GaxiGYYzAaxmGPYXmCft5m4jsx5o5yz3DuBF4yB6iuFREUkRkIta8wS+rajOAiLyMNYTy+yahCUadPX28WdHEkaYOBlSZkhbPssIMEqKDqtuM4aD27j42lTdytLkDQZiaHseywgziokwaM4bnk9Rhz8k7H9g6aFUOZ4//X2svG275UMe+HWs8fKZMmTIu8TqlvbuPn798iMe219DeffbAobGR4Xxk4WS+fs1MkuMiHYrQCHQtnb3818sH+UtZLWd6z55XKCE6go9fkstXrp5hfpwYQ/J6qrCn+XwS+LKqtg5ePcQuOsLy9y9UvQ+4D6CoqChgR1LcefQUdz7yFnWtXayel8NHiyYzZ2IyCBysa+PJHbX8adtRXtxTx71r57GkIGP0gxqGmy2VTXzx0Z2c6uzhIwsm8+GFk5k5IREU9p5o4YmyWh54s5oX3jnBL29ZwIIpqU6HbPgZr7aSsqfUfBJ4RFWfGmKTWs6eT3gy1oxmwy0PSq/sO8na+0uJDA/jyS8s4WcftzKE5LhIkmMjWTQtjX/7yFyevWspqXGR3PrANp7bFbSXw/CC53cd59YHtpESF8mzdy3l3z4yl0XT0kiOjSQ5LpIlBRn898fn8dQXlhAVEcbN95fyyr6TTodt+BlvtpIS4PfAflX972E2ew74pN1aqhhoses+1gHXiEiqPcHLNfayoLO5spEvPLKDmdmJPHXnkhF/1V2Yk8wTdyxh/pRUvvzYTl7dbz7Qxuhe3X+Sf3xsJ/NyU3jyjiVcmJM87Lbzp6Ty1BeWMHNCEl94ZAebKxuH3dYIPd68w1iKNbfuFSLytv34gIjcISJ32Nu8AFRhzR98P/b8y3Zl94+A7fbjh64K8GBSUd/G5x/eQV56PA99ejEZCdGj7pMcF8kfbruEOZOSuftPO9lzrMUHkRqBas+xFu7+007mTErmD5+6xKP6r/SEaB769CKmZcTz+Yd2UH6yzQeRGoEgqCZQKioq0kAZrbart5/Vv3yThrZunvviMnJSYse0f0NbNzf+YhOREWH87UvLTSWl8T7t3X1cf+9GuvsGeO7uZWQmjv6DxN3x02e44RebSI+P5tm7lxITGe6lSA0nicgOVS3yZFvT09shP31hPwfq2vjPj1085swCIDMxmp+vmU9Ncyf3PLPHCxEage6eZ/ZwtLmT/1kzf8yZBcCklFj+86MXc/BkGz/5234vRGgEGpNhOGD74WYe2nKETy+dxoqZWed8nEXT0rj7ikKe2nmM9QfrxzFCI9CtP1jPUzuPcfcVhSyalnbOx7l8ZhafWTaNh0uPsK066EqFjTEyGYaP9fQN8N2n3yEnJZavr5xx3se7a0UBBZnxfO+ZPZzp6R99ByPonenp555n91CQGc9dKwrO+3hfu2YGOSmxfPfpd+jpGxiHCI1AZTIMH/u/zYc5dLKdH9wwZ1x61UZHhPPj1RdRe+oMv369YhwiNALdbzZUUtN8hh+vvojoiPOvd4iLiuCHN86hvL6dBzdXj0OERqAyGYYPtXT28ov1FVw2I5OrZmeP23FLCtK5bu5E7t9YTX1r17gd1wg89W1d3L+xiuvmTqSkIH3cjnvlBdlcPjOTX66vpKWzd9yOawQWk2H40K9er6C1q5dvXztr3I/9jWtm0ts/wM9fLR/3YxuB439eKaenb4BvXDNz3I/9rVWzaO3q5VfmTjZkmQzDR+rbunhw82FumpfDBROTxv34eRnx3LJ4Cn/eXsPRps5xP77h/2qaO3lsew03L55CXkb8uB//golJ3DQ/hz9sPmzuZEOUyTB85Hcbq+ntH+BLVxZ67Rx3rphOuAi/3lDptXMY/uvXGyoJF+GuFdO9do4vXVFIX/8Av9tk6jJCkckwfOBURw9/LD3CBy+e5JVffi7ZSTF8tGgyT+yo4UTLGa+dx/A/dS1dPFFWy0eLJpOdFOO18+RlxPPBiyfxx9IjnOro8dp5DP9kMgwfeHDzYTp7+r36y8/ljssKULXuaIzQ8buNVfSrcsdl59+MdjR3rZhOZ08/D24+7PVzGf7FZBhe1tXbzyNbj3DlrCxmZCd6/Xy5aXFcN3cif95eQ1uXac0SCtq7+/jz9hqunzuR3LQ4r59vRnYiV87K4pGtR+jqNX1/QonJMLzs+V3HaWzv4dPLpvnsnJ9aOo327j7+Ulbrs3MazvlLWQ1t3X18aqnv0tinl02jsb3HDLMfYkyG4UWqygNvHmZmdiJLxrFN/Gjm5aawcGoqD24+TP9A8Awuabxf/4Dy4ObDLJyayrzcFJ+dd0lBOjOzE3lgUzXBNICpMTKTYXjRzprT7D/Ryq1L8rCmB/GdTy3N42hzJ2+UN/j0vIZvvVHewJGmTm5dkufT84oIn1qax4G6NnYcOeXTcxvOMRmGFz2+vYbYyHA+ePFEn5/7mtkTyEiI4k9bj/r83IbvPLr1KOnxUayaM8Hn5/7gxZNIiI4waSyEmAzDSzq6+3h+13GumzuRxJjRJ60Zb1ERYXxkYS6vHainrsV0sgpGJ1u7ePVAPR8tyiUqwvcf5fjoCFbPn8Rf3znB6U7TxDYUeHOK1gdEpF5EhpysQUS+4TYT3x4R6ReRNHvdYRF5x14XGDMiDfK3d07Q0dPPxy/JHX1jL1m7KJf+AeXxshrHYjC85/HtNfQPKGsXOZfGbl40lZ6+AZ5665hjMRi+482fJQ8Cq4Zbqar/oarzVHUe8B1gw6BpWFfY6z2aCcrfPL69hvzMeIqmDj9Ht7dNTY9nSUE6T71Vayomg4yq8tTOY5TkpzM13XudQUcze1IScycn89RO0yIvFHgtw1DVNwBPZ1xZCzzqrVh8raK+nbIjp/hYUa7PK7sHWz0/h8NNnbxdc9rROIzxtau2herGDm5akON0KKyel8OeY61m7u8Q4HgdhojEYd2JPOm2WIG/i8gOEbl9lP1vF5EyESlraPCPFkF/KashPEz4kB98mFddOIHoiDCe3mmKDILJ02/VEh0RxqoLfV/ZPdgHL55EeJiYNBYCHM8wgA8Cbw4qjlqqqguAa4G7ROTS4XZW1ftUtUhVizIzM70d66h6+wd48q1jXDEri6xE743p46mkmEiump3N87uO09tvZksLBr39Azy/+wRXzc4myYEGFYNlJkazbHoGz759nAHT7yeo+UOGsYZBxVGqetz+Ww88DSxyIK5zsqWyicb2bj6ycLLTobzrQ/NzONXZyxuH/OMOzDg/G8sbaO7o4aZ5zt/BunxoQQ7HTp9h+2Ez73cwczTDEJFk4DLgWbdl8SKS6HoOXAMM2dLKH/1193ESoyO4bIbzdzsul87IJDUu0hQZBImndx4nNS6SS/0ojV09O5u4qHCeeduksWDmzWa1jwJbgJkiUisinxGRO0TkDrfNbgL+rqodbsuygU0isgvYBvxNVV/yVpzjqadvgJf21HH17GxiIs9/LuXxEhkexgcvnsTL+07SagYkDGhtXb38fW8d18+d5Ejfi+HERUWwas4E/rr7hBmQMIh5s5XUWlWdqKqRqjpZVX+vqr9R1d+4bfOgqq4ZtF+Vql5sP+ao6k+8FeN4e7OikdauPq6b6/ue3aNZPT+HbjtDMwLXS3vq6O4bYPV8/ymOclk9P4e2rj7WH6h3OhTDS/znJ0oQeH73cZJiIlhe6D9FBS7zc1OYmh7H82Z00YD23K7jTEmLY8EU3w006KklBelkJkabEWyDmMkwxklXbz8v7z3JyjkT/KqowEVEuPbCiWypbKKl0xRLBaKWzl62VDZx7UUTHO/fM5SI8DBWzsnm9YMNnOkxxVLByP++2QLUxvJG2rr9szjKZdWFE+gbUF49cNLpUIxz8OqBk/QNqCMDDXpq1ZyJnOntN6MkBymTYYyTv+4+TkpcJEunZzgdyrDm5iQzMTnG1GMEqHV765iQFMPFk/2vOMplcX4aybGRrNtr0lgwMhnGOOjq7eeVfSdZNWcCkeH+e0nDwoSVcyaw4VADnT19TodjjEFnTx8bDjWwck42YWH+VxzlEhkexlUXZPPKvpOmo2gQ8t9vtwDyZkUjHT39XHuR/xZHuVwzJ5vuvgE2HDRFBoHkjUMNdPUOsNIPhgIZzco52bR29VFa1eR0KMY4MxnGOHhl/0kSoiMozk9zOpRRLcpLIzUukpdMkUFAeWlPHalxkSzK8/80dumMTGIjw03RZxAyGcZ5GhhQXtlfz2UzMomO8J/OesOJCA/j6tnZvLa/np4+U2QQCHr6Bnh1fz1Xz84mwo+LPF1iIsNZMSuTdXtPmjnlg4z/pz4/t/tYCw1t3Vw1O8vpUDy26sIJtHX3sbmy0elQDA9srrRa4PnDyLSeWjlnAo3t3ew8aub7DiYmwzhPr+w7SXiYsGJm4GQYSwoySIiOMC1ZAsS6vXUkREewpMB/W+ANdsWsLKLCw0yxVJAxGcZ5emX/SS7JSyUlLsrpUDwWExnOZTMyeXV/vZmJz8+pKq/aRZ7+ND7ZaBJjIikuSOdVM0xIUDEZxnmoae7kQF0bV12Q7XQoY7ZiVhb1bd3sPd7qdCjGCPYeb6W+rZsVswLnDtblipmZVDd2UN3YMfrGRkAwGcZ5eGW/1WP66tmBl2FcPjMTEcxAcX7O9f+5fKb/jU82mitmWZ8Lk8aCh8kwzsMr+09SmJXA1PR4p0MZs4yEaOZOTuG1g+bD7M9eO1jPxZOTyUiIdjqUMZuSHkdBZjzrTRoLGibDOEetXb1srWrmqgC8u3BZMTOTt2tO09Te7XQoxhCaO3p4u+Z0QBZHuayYmcXWqmY6us3IAsHAZBjnaFN5I30DypUB/GG+YlYWqrDBTN3qlzYcqkeVgGqBN9gVs7Lo6R/gzQrThDsYeHPGvQdEpF5EhpxeVUQuF5EWEXnbftzjtm6ViBwUkQoR+ba3YjwfGw42kBQTwbxc/x0IbjQXTrKKOl4zZcx+6bUDDWQkRHNRTrLToZyzorw0EqIjTLFUkPDmHcaDwKpRttmoqvPsxw8BRCQc+CVwLTAbWCsis70Y55ipKhsONbC8MDMget4OJyxMuHxmJm8caqDPDBTnV/r6B9hwsJ7LZ2b69WCDo4mKCGPZ9AzWH2gwTbiDgDenaH0DaD6HXRcBFfZUrT3AY8CN4xrceTp0sp261i4umxF4LVcGu2JWFq1dfbx19LTToRhudtacprWrL6CLo1yumJVFXWsX+0+0OR2KcZ6c/nlcIiK7RORFEZljL8sBaty2qbWXDUlEbheRMhEpa2jwTVn8hkPW7fWlQZBhLCvMICJMTLGUn3ntQD0RYcLyGYHTu3s4l8+yPiemWCrwOZlhvAVMVdWLgf8FnrGXD3X/Pey9rKrep6pFqlqUmembL/ANhxqYNSGRCckxPjmfNyXFRHJJXhqvmw+zX3n9YAMLp6aSFBPpdCjnLSsxhotykk1/jCDgWIahqq2q2m4/fwGIFJEMrDuKXLdNJwN+M6t8R3cf26tPBcXdhcvyGRkcqGujvrXL6VAMoL6ti/0nWoMrjRVmsLPmNG1dZj75QOZYhiEiE8SeyV5EFtmxNAHbgUIRmSYiUcAa4Dmn4hystKqJnv6BoKi/cLm00Hovm0zTR7/gaoLq+r8Eg+WFmfQPKFsqzaRKgcybzWofBbYAM0WkVkQ+IyJ3iMgd9iYfAfaIyC7gXmCNWvqAu4F1wH7gcVXd6604x2rDoQZiI8Mpykt1OpRxM3tiEmnxUWwqNxmGP9hY3khqXCRzJiU5Hcq4WTA1hbiocPOjJMBFeOvAqrp2lPW/AH4xzLoXgBe8Edf52nCogSUF6QExWZKnwsKEpdMzeKO8EVXFvvEzHKCqbCxvZFlhYDenHSw6Ipzi/HQ2mh8lAc3pVlIB5XBjB0eaOrksAAeCG83ywgwa27s5UGeaPjrp4Mk2Gtq6WV4Y+K2jBltemEF1Ywc1zZ1Oh2KcI5NhjMFG+3Z6eRCVLbu4vqA2lpthQpy08ZArjQVnhgGYu4wAZjKMMdhc0UhOSix56XFOhzLuJibHUpiVYD7MDttY0cj0rAQmJsc6Hcq4K8hMYGJyDJsqzI+SQGUyDA8NDChbqppYUpAetGX8ywoz2FbdTFdvv9OhhKSu3n62VjUF5d0FgIiwvDCDTeWN9A+YYUICkckwPLTvRCunO3tZOj04P8xgNePs7htg++FzGdHFOF9lh0/R3TcQVM1pB1temElrVx+7a81QNIHIZBgecrWNX1KQ7nAk3rM4P43IcDHFUg7ZWNFAZLiwOD/N6VC8Zun0DERMPUagMhmGhzZVNFKYlUBWUuAPBzKcuKgIFk5NNR9mh2wqb2Th1FTiorzW2t1xafFRXDgp2fT5CVAmw/BAd18/2w83B3VxlMuy6RnsP9FKc0eP06GElNOdPew70crSguBPY0unZ7Cz5hSdPWYWvkBjMgwP7Dx6mq7egaAujnIpsd9jaZUZwsGXtlU3owrFIZLGevuVssOnnA7FGCOTYXhgc0UjYQKL84P/wzx3sjWEw+ZKU2TgS1uqmoiJDGPu5MCdXc9Tl+SlEhEmbDbjSgUck2F44M3KJuZOTiE5NvCHmh5NZHgYi6almUHifKy0qpmFU1ODasiZ4cRFRTB/SgpbzF1swDEZxijau/vYVXOapdOD/+7CZUlBOpUNHZw0w537xOnOHg7UtVI8LXTSWElBBu/UnqbVDHceUEyGMYpt1U30DWhIVEa6lORb79XcZfjGVrv+oiQE6i9cSvLTGVDYVmX6/ASSETMMEZksIl8XkWdFZLuIvCEivxKR60QkJDKbTeVNREeEsWBq8AxnPprZk5JIiokw9Rg+Uvpu/UWK06H4zPwpKURHhJl6jAAzbINvEfkD1lzafwX+DagHYoAZwCrguyLybVV9wxeBOmVzZSNFeanERAZ/2bJLeJhQnJ9uyph9ZEtlE0VT04iKCInfYADE2HPKmDQWWEZKof+lqteo6r2qullVK1R1j6o+papfBC5nhKlTReQBEakXkT3DrL9FRHbbj80icrHbusMi8o6IvC0iZef65s6Xa7jvJSFUHOWypCCdmuYzZihqLzvV0cOBujaKg7h393CWFJg+P4FmpAxjlYhMHm6lqvaoasUI+z+IdScynGrgMlWdC/wIuG/Q+hWqOk9Vi0Y4hle5bpdDocPeYCUFph7DF7ZWW2X4xSHQZHsw13s2fX4Cx0gZRg6wxa63+IKIjOlb0y6qGrZGy75rcfXcKQWGzZycsrmikcSYCC7KCf628YPNyE4gPT7K1GN4WWlVE7GR4SFVf+Eyd3Iy8abPT0AZNsNQ1a8AU4DvAXOB3SLyooh8UkQSxzmOzwAvup8e+LuI7BCR20faUURuF5EyESlraBjfcfY3VzZRnJ9OeBBNlekpEaGkwKrHUDVDUXtLaVUTRXmpIVV/4WL6/ASeEVOpWjao6heAXODnwFeAk+MVgIiswMowvuW2eKmqLgCuBe4SkUtHiPE+VS1S1aLMzPEbFvrY6TMcbe6kJASLClyWFGRwsrWbqsYOp0MJSu/VX4R2GjN9fgKHRz9rROQi4IfAL4Ee4J/G4+QiMhf4HXCjqr77M0NVj9t/64GngUXjcb6x2GqXq4byh9nVL8A0ffSOrdWuNBZ6Fd4urjRm7jICw7AZhogUisj3RGQf8CegE7hGVRer6s/P98QiMgV4CvgHVT3ktjzeVeQlIvHANcCQLa28qbSqieTYSGZNGO/St8CRlx7HxOQYtpgyZq8orWomNjKci3JCr/7C5YKJSSTHRpp6jAAx0sD764BHgY+r6jtjPbCIPIrV9DZDRGqB7wORAKr6G+AeIB34lT3laZ/dIiobeNpeFgH8SVVfGuv5z9fW6mYWTUsjLATrL1xTZmjuAAAgAElEQVRc9RivH2xgYEBD+lp4QyjXX7hYfX7STH+MADFshqGq+e6vRSTJfXtVHbFPv6quHWX9Z4HPDrG8Crj4/Xv4zvHTZzjS1MknS/KcDMMvlOSn89Rbxzh4so0LJiY5HU7QaLbrLz548SSnQ3FcSX466/aepKa5k9y0OKfDMUYw6k8bEfm8iJwEdgM77Idjnel8wZQtv2eJ3QfF1GOMr23Vpo7MxZXGTD2G//PkXvjrwBxVzVPVafYjf9S9AtjWqmaSYiKYNcH8os5JiWVKWpzpXDXOtlS6+l+EXh+fwQqzrD4/Jo35P08yjEqsCu+QUVrVxKJpodn/YijF+Wlsq25mYMD0xxgvpVXNFOWlEhkeuvUXLiLW2GWlps+P3/MktX4H2CwivxWRe10PbwfmlBMtZzjc1GmKo9wU56fTcqaX/XWtTocSFJrauzl4MrT7XwxWnJ/G8ZYuaprPOB2KMYKRWkm5/BZ4DXgHGPBuOM7bWhW6Y/sM570xf5qZM8kUoZyvbSE8ftRw3MeVmpJuKr79lScZRp+qftXrkfiJrdVNJMZEmBZBbialxDI13arH+MyyaU6HE/BKq5qIizL1F+6mZyWQkRDFlqomPnZJrtPhGMPwpEhqvT1e00QRSXM9vB6ZQ0qrmlk8Lc3UXwxSPC2drVVN9Jt6jPNm1V+kmfoLNyLCYlOP4fc8SbE3Y9djEOTNautauqhu7DBFBUMoLkijtauP/SdMPcb5eK/+Imh/c52z4vx0TrR0cdTMweK3Ri2SUtWQKYNw9b9YPM1kGIO5rklpVRMXhuBw7+MllOe/GE2JnYmWVjUxNT3e4WiMoYw0ltSykXYUkSQRuXD8Q3JOaVUzidERzJ5k6i8Ge68eY8QO/sYoXPUXoTjHymgKMq16DJPG/NdIdxgfFpF/B17CKoZqwJrTezqwApgKfM3rEfrQ1qomFpn6i2GV5Kfzwjsn6B9Qc43OkTV+lKm/GIqrHmNLpVWPYY8nZ/iR0SZQug44AXwUaxrVrwKFwG9V9VJV3e6TKH3gZGsXVab+YkTF+emmHuM8NLZ3c+hke0jPsTKakvx06lq7ONJk6jH80Yh1GPYUqvfbj6DmGpZgsamMHNZitzJmU48xdu/18TFpbDju/THyMkw9hr8x98W2rdV2/YXpfzGsicmx5KWbcaXOVWlVE/FR4SazHUFBZjwZCdEmjfkpk2HYSquauGRaGhGmbHlExfnpbK1uNv0xzoGpvxidNa5UGqVVzaY/hh8yKReob+2iqqGDxdNMUcFoSgrSaTP1GGPW2N5NeX27qSPzQLGpx/BbnsyHEWdP1Xq//bpQRK735OAi8oCI1IvIkFOsiuVeEakQkd0issBt3a0iUm4/bvX0DZ0L0zbec+79MQzPmfoLz707z7dJY37HkzuMPwDdQIn9uhb4sYfHfxBYNcL6a7FaXRUCtwO/BrCHHvk+sBhYBHxfRFI9POeYlVY1kRAdwRzT/2JUE5JjmJYRbya7GSNX/YXpfzG6/Ix4MhNNPYY/8iTDKFDVfwd6AVT1DOBRA2lVfQMYqRfOjcBDaikFUkRkIrASeFlVm+2WWi8zcsZzXkqrmrgkL9XUX3jINT+Gqcfw3BZTR+YxMz+G//Ik9faISCygACJSgHXHMR5ygBq317X2suGWv489MGKZiJQ1NDSMOYCu3n6SYiNZak8TaYyuOD+dtu4+9h039RieaGjrpsLUX4xJcX4aJ1u7OWzqMfyKJxnG97F6e+eKyCPAq8A3x+n8Q92p6AjL379Q9T5VLVLVoszMzDEHEBMZztN3LuWzy4N61tlx5d5W3hjdVjN/95iZNOafRs0wVPVl4EPAbcCjQJGqvj5O568F3Ae/nwwcH2G54Qeyk2LIz4g3H2YPuerILjR1ZB5z1WOYujL/4kkrqQVY40adwPrSniIiBSLiyeRLo3kO+KTdWqoYaFHVE8A64BoRSbUru6+xlxl+YnF+uqnH8FBpVbOpIxsjEaHE1GP4HU9S8K+AUuA+rCFCtgCPAYdE5JqRdhSRR+3tZ4pIrYh8RkTuEJE77E1eAKqACvvYdwKoajPW2FXb7ccP7WWGnyjOT6Otu4+9x1ucDsWv1bd1mfqLc1Scn059WzfVjR1Oh2LYPLlLOAx8RlX3AojIbOAbWF/oTwF/H25HVV070oHV+ulw1zDrHgAe8CA+wwElbmXMcyenOByN/zJzxJ+74nfHLmsmPzPB4Wj81xuHGjja3MnaRVO8Poq0J3cYs1yZBYCq7gPmq2qV98Iy/F1WUgz5mfFm7oJRmD4+525aRjxZpj/GqB7ddpRfv17pkykHPMkwDorIr0XkMvvxK6ziqGjsvhlGaCrOT2d7dTN9/QNOh+K3TB+fc+fqj7HF1GMMS1XZWt3ss1G2PUnFt2HVMXwZ+ApWncNtWJnFCm8FZvi/d/tjmHGlhlTf1kVlg5lj5XyUFKTT0NZNlanHGFJ5fTvNHT0+S2OezOl9Bvgv+zFY+7hHZASM4mnvzY9h6jHez1V/4RobyRg79/4YBaYe431cxXW+mpTLk2a1hSLyhIjsE5Eq18MXwRn+zVWPYdrKD21LVZOZY+U85aXHkZ0UberKhrG1qplJyTFMTo31yfk8HXzw10AfVhHUQ8DD3gzKCBwl+elsP3zK1GMMwcyxcv7MuFLDs+ovmijOT/fZ/OeepORYVX0VEFU9oqr/DFzh3bCMQFGcn057dx97zbhSZ3HNsWKGMz9/xflWPUZlg6nHcFfZ0E5je49Pp5X2JMPoEpEwoFxE7haRm4AsL8dlBAj3eb6N95SaOVbGjRlXamhbHOjj40mG8WUgDvgSsBD4BPBJbwZlBI6sxBgKMs24UoOVmvqLcZOXHseEpBiTxgYprWpiYnIMU9LifHZOTzKMPFVtV9VaVf2Uqn4YmOLtwIzAUWzqMd6ntLKJRab+YlyYeb7fT1XZWtXM4mlpPqu/AM8yjO94uMwIUSUFVj3GHlOPAcDJ1i6qGk3/i/FUnJ9OY7upx3CpbOigsb3b52ls2H4YInIt8AEgR0TudVuVhNViyjCAs+f5npdr+mO4ik5MhjF+XNdyS1UT07NMfwyn5lgZ6Q7jOLAD6LL/uh7PYU2hahgAZCZGMz0rwZQx296tvzDjR42bqaYe4yylVc1kJ0UzNd139Rcwwh2Gqu4CdonIH1XV3FEYIyrOT+Ppt47R1z8Q8uX2WyqbWJyf5pPB4EKFiFBSkM7G8gZU1afl9v5GVdlS2ciy6Rk+vw7DfrJF5B0R2Q28JSK7Bz98GKMRAIrz0+no6Q/5eoxjp89wuKmTkgIzR/x4K85Po7G9h8qG0B6RqLze6n+xxIE0NtJYUtf7LAoj4L1bxlwZ2vUYrmFSlpjxo8bde/UYzUzPSnQ4Gue40pgTY5QNe4dh9+o+oqpHsOoxLrIfZ+xloxKRVSJyUEQqROTbQ6z/mYi8bT8Oichpt3X9buueG/tbM3wpIyGaQlOPwZbKJtLio5iZHbpfaN4yJS2OicmmHmNzZSO5abHk+rD/hYsngw9+DNgGfBT4GLBVRD7iwX7hwC+Ba4HZwFp7tr53qepXVHWeqs4D/hdrBj+XM651qnqDx+/IcExxfjplh5vpDdH+GK6y5eL8NMJM/cW4c40rtTWEx5XqH1BKq5p9NjrtYJ7UTn4XuERVb1XVTwKLgO95sN8ioEJVq1S1B2se8BtH2H4t8KgHxzX81Lv1GMdCc57vI02dHG/pMvUXXuSqx6ioD816jP0nWmk50+tI/QV4lmGEqWq92+smD/fLAWrcXtfay95HRKYC04DX3BbHiEiZiJSKyOrhTiIit9vblTU0NHgQluEti93mYA5Fm039hdeV5FtflKFaLOVk/QV49sX/koisE5HbROQ24G/ACx7sN9Q9+XD3kWuAJ1S1323ZFFUtAm4Gfi4iBUPtqKr3qWqRqhZlZmZ6EJbhLRkJ0czIDt16jM2VjWQnRZOfEe90KEErNy2WSckxIfyjpJGCzHiyk2IcOf+oGYaqfgP4LTAXuBi4T1W/5cGxa4Fct9eTsToDDmUNg4qjVPW4/bcKeB2Y78E5DYdZ40qFXj2GqlJa1USJD+cmCEWhPD9Gb/8A26qbHZ3B0ZNK768A21T1q3Yl9dMeHns7UCgi00QkCitTeF9rJxGZCaQCW9yWpYpItP08A1gK7PPwvIaDivPT6ezp550Qq8dwsm18qCnOT6epo4fyEKvH2F3bQkdPv6NpzJMiqSRgnYhsFJG7RCTbkwPbvcPvBtYB+4HHVXWviPxQRNxbPa0FHtOzfy5cAJSJyC5gPfCvqmoyjACwaFpozo+xuaIRMPN3+0Kozo/hD2OUjdRxDwBV/QHwAxGZC3wc2CAitap6lQf7vsCg+g5VvWfQ638eYr/NWH0+jADzXj1GM3de7nQ0vrO5ssmxtvGhJjctlpyUWEqrmvhkSZ7T4fjM5spGLpiYRFp8lGMxjGXQn3qgDquVlJlxzxhWSYj1x7Daxjc51jY+1IgIi0Nsfoyu3n7KDp9yPI15UofxBRF5HXgVyAA+p6pzvR2YEbhCrR5j/4lWWrv6TP2FDxXnp9McQvUYO4+eprtvwPEm257cYUwFvqyqc1T1+6YuwRiNqx7D1WY82G2uNPUXvlbiNnZZKNhS1USYwCK7r5NTPGlW+21VfdsXwRjBIT0hmpnZiSFTKbm5ssnRtvGhaHLqe/UYoWBLZSMXTU4hKSbS0ThCe+ICw2uK89MoO3wq6Osx/KFtfChy1WNsrW5mYCC46zE6e/rYefS04/UXYDIMw0tKCtI509vPrprTo28cwHbVnKbT4bbxoarErsc4eLLN6VC8alt1M30D6nj9BZgMw/CSkvwMwgQ2ljc6HYpXbSxvRMSMH+WEZYVWJr0pyNPYpvJGoiLCuCTP2foLMBmG4SXJcZHMnZzCxvLgHhByY3kDcyenkBLnXNv4UDUxOZbpWQm8EfRprJFFeWnERoU7HYrJMAzvubQwg7drTtNyptfpULyi5Uwvb9ec5tJCUxzllOWFGWyrbqart3/0jQPQydYuDp5sY7mfpDGTYRhes3xGJgMavE0ft1Q2MaCwbLp/fJhD0aWFmXT3DVB2+JTToXiFq7htmckwjGA3LzeFhOiIoC2W2ljeQHxUOPOnpDodSshanJ9GZLgEdRrLSIjigglJTocCmAzD8KLI8DCK89ODtuJ7Y3kjJQXpREWYj5FT4qIiWDg1lTeCMI0NDCibKhpZNj3Db6b8NSnd8KpLZ2RwtLmTI00dTocyro40dXC0uZPlhWbSLqctL8xk/4lWGtq6nQ5lXB2oa6Oxvcev0pjJMAyvcpXvB9tdxkY/K1sOZa4K4Tcrgi2NWcVs/pTGTIZheNW0jHhyUmKDrox5Y3kDOSmxZjpWPzBnUjKpcZFB17x2Y3kjM7MT/WrIGa9mGCKySkQOikiFiHx7iPW3iUiDiLxtPz7rtu5WESm3H7d6M07De0SES2dksLmyib4gGSakr3+AzZVNLC/MMNOx+oHwMGHp9Aw2lTcGzXDnXb39bDvc7DfNaV28lmGISDjwS+BaYDawVkRmD7Hpn1V1nv34nb1vGvB9YDGwCPi+iJimKAFqeWEmbV197KoNjmFCdtWepq2rz6+KCkLdpYWZ1Ld1B80wIVurm+npG/C7NObNO4xFQIWqVqlqD/AYcKOH+64EXlbVZlU9BbwMrPJSnIaXLZ2eQXiYsP5AcBQZrD/QQHiYsHy6/1RGhrpLZ1j/i+BJY/XERIY5Oh3rULyZYeQANW6va+1lg31YRHaLyBMikjvGfRGR20WkTETKGhqCI7EEm+TYSBZOTeW1A/VOhzIuXjtQz8IpqSTHOTvUtPGeCckxzJ6YxPogSGOqyvqD9SwpyCAm0vnhQNx5M8MYqnB3cAHj80CePYPfK8D/jWFfa6HqfapapKpFmZnmF5+/WjEzi30nWqlr6XI6lPNS19LFvhOtXD7LpDV/s2JWJjuOnqKlM7CHoqlq7OBIUycrZvpfGvNmhlEL5Lq9ngwcd99AVZtU1dV4+n5goaf7GoHlilnWNPCvHwzsX4Cu+F3vx/AfV8zKon9AA761lOsuaYUfpjFvZhjbgUIRmSYiUcAa4Dn3DURkotvLG4D99vN1wDUikmpXdl9jLzMC1IzsBHJSYgO+WOq1A/VMSo5hZnai06EYg8zLTSU1LjLgi6XWH6xnRnYCk1PjnA7lfbyWYahqH3A31hf9fuBxVd0rIj8UkRvszb4kIntFZBfwJeA2e99m4EdYmc524If2MiNAiQgrZmWyqaKR7r7AHFm0u6+fTRWNrJiVZZrT+qHwMOGyGZm8fqiB/gCdha+9u49t1c1+eXcBXu6HoaovqOoMVS1Q1Z/Yy+5R1efs599R1TmqerGqrlDVA277PqCq0+3HH7wZp+EbK2Zm0dnTz7bqwMz7t1U309nTz4qZ/vlhNqxinOaOnoBtwr2pvIHefvXbNGZ6ehs+s6Qgg+iIsIBt+rj+QANREWEsme5fTR2N91w2I5MwgdcDtFhq/YEGEmOsARX9kckwDJ+JjQqnpCCd9QFa8b3+YD0l+enERUU4HYoxjJS4KBZMSeW1AExjrua0l87IJDLcP7+a/TMqI2itmJlFdWMH1Y2BNXqtK2Z/bOponG3FrCz2HGulvjWwmnDvPd5KfVu33xZHgckwDB9zNUd9Zd9JhyMZG1e8V16Q7XAkxmjeTWP7A+su4+V9JxGBy/34R4nJMAyfyk2LY86kJF7aW+d0KGPy0t46Zk9MIjfN/5o6GmebNSGRqelxAZfG1u2t45K8NDISop0OZVgmwzB8btWcCew4cipgigzqW7vYceQUqy6c4HQohgdEhFVzJrC5opGWM4HR67u6sYMDdW2smuPfacxkGIbPub541wVIsZQrTpNhBI6VF06gb0B57UCApDH7bmiln6cxk2EYPjc9K4H8zHjW7QmMIoN1e+rIz4inMCvB6VAMD82bnEJ2UjQvBUgae2lPHXMnJ5OTEut0KCMyGYbhc64igy1VTZzu7HE6nBGd7uyhtKqJlRdOML27A0hYmLByzgQ2HGrgTI9/jyxwouUMb9ecZqWfF0eByTAMh6ycM4H+AfX7liyv7q+nb0AD4sNsnG3lnAl09Q6w4ZB/dxT9+16r2CwQ0pjJMAxHzJ2czMTkGL8vMnhpbx0Tk2OYm5PsdCjGGC2alkZKXOS79QP+6qU9dUzPSmB6ABR5mgzDcISIVWTwRnkDHd19ToczpI7uPt441MDKORMICzPFUYEmMjyMqy7I5pX9J+np88/55Js7etha3eT3raNcTIZhOGbVhRPo6Rvw2yHPXz/YQHffANfMMZ31AtWqORNo6+rjzcpGp0MZ0sv76hjQwCiOApNhGA66JC+NrMRonn3bP+fGeubtY2QlRrN4mhlsMFAtn5FBUkwEz/lrGtt5nLz0OC7MSXI6FI+YDMNwTHiYcOO8Sbx+sJ7mDv9qLXWqo4fXD9Zz47xJhJviqIAVHRHOdXMn8dKeOr8r+jx++gyl1U2snp8TMC3wTIZhOOqm+ZPpG1D+9s4Jp0M5y9/eOUFvv7J6fo7ToRjn6ab5OZzp7edlP+so+tyu46ha8QUKr2YYIrJKRA6KSIWIfHuI9V8VkX0isltEXhWRqW7r+kXkbfvx3OB9jeBwwcREZmYn8szOY06Hcpandx5jRnYCsycGRlGBMbyiqankpMTylJ+lsWd2HmPBlBSmpsc7HYrHvJZhiEg48EvgWmA2sFZEZg/abCdQpKpzgSeAf3dbd0ZV59mPGzCCkoiwen4OO46c4mhTp9PhAHC0qZMdR04FVFGBMbywMGH1/ElsKm+gvs0/xi/bf6KVA3VtAXV3Ad69w1gEVKhqlar2AI8BN7pvoKrrVdX1LVEKTPZiPIafunHeJMCqZPYHrjhWzwusD7MxvJvm5zCg8Pwu/yj6fGbnMSLChOvmTnI6lDHxZoaRA9S4va61lw3nM8CLbq9jRKRMREpFZPVwO4nI7fZ2ZQ0N/t2j0xjapJRYivPTeGbnMVTV0VhUlWd2HqM4P41Jfj6uj+G56VmJXJST7BdFn/0DyrNvH+fymZmkxUc5Hc6YeDPDGOpefshvAxH5BFAE/Ifb4imqWgTcDPxcRAqG2ldV71PVIlUtysz034lHjJHdND+HqsYOdtW2OBrH7toWqho7Aq6owBjd6vk5vHOshYr6Nkfj2FrVRF1rV0A2qPBmhlEL5Lq9ngy8rzG0iFwFfBe4QVW7XctV9bj9twp4HZjvxVgNh1170USiI8J4vKxm9I296M9lNURHhLHqwomOxmGMvxsunkREmPB4Wa2jcfy5rIbEmAiuCsDZG72ZYWwHCkVkmohEAWuAs1o7ich84LdYmUW92/JUEYm2n2cAS4F9XozVcFhSTCTXz53EszuPOdZevqO7j2d3HuP6uZNIjo10JAbDezITo7nqgmye2FFLd58zI9g2d/Tw4jt1fGh+DjGR4Y7EcD68lmGoah9wN7AO2A88rqp7ReSHIuJq9fQfQALwl0HNZy8AykRkF7Ae+FdVNRlGkLt58RQ6evp5bpczvXKf23Wcjp5+bl48xZHzG9538+IpNHf0sG6vM30yntxRS0//ADcvnjr6xn4owpsHV9UXgBcGLbvH7flVw+y3GbjIm7EZ/mfBlBRmTUjkka1HWHNJrk+btKoqf9p6lFkTElkwJcVn5zV8a9n0DHLTYnmk9Ag3XOzbFkoDA8qj246ycGoqMyck+vTc48X09Db8hohwS/FU9hxr5a2jp3x67reOnuKdYy3csniK6XsRxMLChJsXTWVrdTP7T7T69NwbKxqpauzglgC+gzUZhuFXPrwgh6SYCB7YdNin531g02GSYiL40ALTFSjYrV2US2xkOH94s9qn531gUzWZidFcH2B9L9yZDMPwK3FREaxdPIUX95yg9pRven7XnurkxT0nWLt4CvHRXi2lNfxASlwUH16YwzNvH6exvXv0HcZBRX0bGw418MniqURFBO7XbuBGbgStW0vyEBGf3WX84c3DiAifLMnzyfkM5922ZBo9fQM8tPmwT873u43VREeEBXyDCpNhGH5nUkosq+fl8KdtR2jy8i/ApvZuHtl6hBvnTSLH9OwOGdOzElg5J5sHNx+mtavXq+c6dvoMT75Vy5pLcklPiPbqubzNZBiGX7pzRQHdfQP8fpN3y5l/v6ma7r4B7rx8ulfPY/ifu1cU0trVx8Nbjnj1PPdtqEQVbr9syMEqAorJMAy/VJCZwAcumshDW454bXKl5o4eHtpyhA9cOJHpWQleOYfhvy6anMxlMzL5/aZq2rx0l1HX0sVj22v48ILJQXEHazIMw299+cpCOnv6+MVrFV45/i9eq6Czp49/vKrQK8c3/N9Xr55Bc0cP979R5ZXj/+zlQ6jC3VcExx2syTAMv1WYnchHF+bycOlhaprHt8VUTXMnD5ce5iMLJzMjOzA7URnn7+LcFK67aCL3b6we97kyyk+28ZcdNXyieCq5aXHjemynmAzD8GtfuXoG4WHCT/62f1yP+9MX9hMmwleunjGuxzUCzzdWzqS3f4B/f+nguB1TVfnhX/cRHxURNHcXYDIMw89NSI7hi1cU8tLeOl47MD7j/7x24CQv7qnjS1cWMjE58MuVjfOTlxHPZ5fn88SOWrZWNY3LMZ/ffYKN5Y187ZoZATfnxUhMhmH4vc8tz6cwK4HvPbOX9vMcyba9u497nt1LYVYCn1ueP04RGoHuH68sZHJqLP/09Dt09Z7fSLanO3v40V/3MXdyMv8QZH17TIZh+L2oiDD+9cMXcaLlDPc8s+e8jnXPs3s4fvoM//KhiwK6x60xvmKjwvnpTRdR2dDBT1849+JPVeWbT+zmdGcPP73pIsLDgmtcMvOJMQLCwqlpfOnKQp7aeYy/nOMkS0/sqOWpt47xpSsLKcpLG+cIjUB36YxMPrtsGg9tOcKL75zb3N8PbTnC3/ed5FurZnFhTvI4R+g8k2EYAeOLVxSypCCdf3r6HTZXNo5p382VjXznqd2U5Kdz94rgqYQ0xtc3V81iXm4KX3n8bXaOccTkV/ef5AfP7+XKWVl8euk0L0XoLJNhGAEjPEz49ScWMi0jns8/tINt1c0e7bf9cDOff3gHeenx/OYTC4kIN8neGFpURBi/u7WIrMQYPv3gdnbXnvZov43lDdz9p53MmZTMvWvnExZkRVEuXv3kiMgqETkoIhUi8u0h1keLyJ/t9VtFJM9t3Xfs5QdFZKU34zQCR3JsJA9+ahGZSdF84vdbeXJHLao65LaqylNv1XLL77aSmRjNg59eRHKcmXrVGFlGQjQPfXoR8dERrLmvlBdGKJ5SVR7ZeoRP/WE7U9PjeOC2S4J6xGMZ7sN23gcWCQcOAVcDtVhzfK91n2pVRO4E5qrqHSKyBrhJVT8uIrOBR4FFwCTgFWCGqo7YfKGoqEjLysq88n4M/3Kqo4fP/9G6y7h0Ria3L89nSUE6YWHCwICypaqJ375RxRuHGliUl8Zv/2EhqUHUvNHwvvq2Lj73f2Xsqm3hqguy+ezyaSzKSyMsTOgfUDaWN/CbDZWUVjWzvDCDX96ygKSYwPtBIiI7VLXIo229mGGUAP+sqivt198BUNV/cdtmnb3NFhGJAOqATODb7tu6bzfSOU2GEVr6B5SHtxzmZ6+U03Kml+iIMDISomls76a7b4Dk2Ei+fFUhnyzJC7rWKoZv9PZbA2D+8rUK2rr7iIkMIz0+moa2bnr6B0iLj+IbK2fy8aLcgC2GGkuG4c17pxzAvTlLLbB4uG1UtU9EWoB0e3npoH1zhjqJiNwO3A4wZUpgjzVvjE14mHDb0mmsWTSFV/afZHdtC/WtXWQlxXBRTjJXz84mJjLc6TCNABYZHsYdlxVwa0ke6/bWsedYC43t3WQnxTB/SgpXzAWR38UAAAjASURBVMoOqebZ3swwhspuB9/ODLeNJ/taC1XvA+4D6w5jLAEawSEmMpzr504K6KkvDf8WGxXO6vk5rJ4/5O/WkOHNrLEWyHV7PRk4Ptw2dpFUMtDs4b6GYRiGD3kzw9gOFIrINBGJAtYAzw3a5jngVvv5R4DX1KpUeQ5YY7eimgYUAtu8GKthGIYxCq8VSdl1EncD64Bw4AFV3SsiPwTKVPU54PfAwyJSgXVnscbed6+IPA7sA/qAu0ZrIWUYhmF4l9daSTnBtJIyDMMYm7G0kgqd6n3DMAzjvJgMwzAMw/CIyTAMwzAMj5gMwzAMw/BIUFV6i0gDcOQcd88AxjZmtm+YuMbOX2MzcY2NiWvsziW2qaqa6cmGQZVhnA8RKfO0pYAvmbjGzl9jM3GNjYlr7LwdmymSMgzDMDxiMgzDMAzDIybDeM99TgcwDBPX2PlrbCausTFxjZ1XYzN1GIZhGIZHzB2GYRiG4RGTYRiGYRgeCfoMQ0RWichBEakQkW8PsT5aRP5sr98qInlu675jLz8oIisdiO2rIrJPRHaLyKsiMtVtXb+IvG0/Bg8b7+24bhORBrfzf9Zt3a0iUm4/bh28r5fj+plbTIdE5LTbOm9erwdEpF5E9gyzXkTkXjvu3SKywG2dN6/XaHHdYsezW0Q2i8jFbusOi8g79vUa1xE9PYjrchFpcft/3eO2bsQ04OW4vuEW0x47TaXZ67x5vXJFZL2I7BeRvSLyj0Ns45s0pqpB+8AaVr0SyAeigF3A7EHb3An8xn6+Bviz/Xy2vX00MM0+TriPY1sBxNnPv+CKzX7d7uA1uw34xRD7pgFV9t9U+3mqr+IatP0XsYbU9+r1so99KbAA2DPM+g8AL2LNJFkMbPX29fIwriWu8wHXuuKyXx8GMhy6XpcDfz3fNDDecQ3a9oNY8/f44npNBBbYzxOBQ0N8Jn2SxoL9DmMRUKGqVaraAzwG3DhomxuB/7OfPwFcKSJiL39MVbtVtRqosI/ns9hUdb2qdtovS7FmHvQ2T67ZcFYCL6tqs6qeAl4GVjkU11rg0XE694hU9Q2s+VyGcyPwkFpKgRQRmYh3r9eocanqZvu84Lv05cn1Gs75pM3xjsuX6euEqr5lP28D9gOD54r1SRoL9gwjB6hxe13L+y/0u9uoah/QAqR7uK+3Y3P3GaxfEC4xIlImIqUistqBuD5s3/o+ISKu6XS9ec08PrZddDcNeM1tsbeulyeGi93baWwsBqcvBf4uIjtE5HYH4ikRkV0i8qKIzLGX+cX1EpE4rC/dJ90W++R6iVVkPh/YOmiVT9KY12bc8xMyxLLB7YiH28aTfc+Hx8cXkU8ARcBlbounqOpxEckHXhORd1S10kdxPQ88qqrdInIH1h3aFR7u6824XNYAT+jZszR663p5wqk05hERWYGVYSxzW7zUvl5ZwMsicsD+Be4Lb2GNb9QuIh8AnsGaptkvrhdWcdSbqup+N+L16yUiCViZ1JdVtXXw6iF2Gfc0Fux3GLVArtvrycDx4bYRkQggGeu21JN9vR0bInIV8F3gBlXtdi1X1eP23yrgdaxfHT6JS1Wb3GK5H1jo6b7ejMvNGgYVF3jxenliuNi9ncZGJSJzgd8BN6pqk2u52/WqB55mfItjR6T6/9u7mxCryjiO499fIEoSZLhIFyJOmaDlDAXBZOveIGrhpiDK2QxluwJhQCLQhNnUohbRQoIINCKaihYDkqGZCGlDRG8OuIlK6MUoJPDf4nlu88zl3PE0c8+5F/l94MJ5ec49/3nuufc55zxn/k/8ERF/5umPgFWS1jME9ZUtdXw1Ul+SVpEai7ci4t2KIu0cY0100gzLi3QFdZ50e6LTSba9q8wzLO70PpKnt7O40/s8/e30rhPbGKmT79au5euA1Xl6PfAdfer8qxnXhmL6UeBULHSwzef41uXpm9qKK5e7jdQBqTbqq9jHZnp34j7E4g7J003XV824NpH65sa7lq8FbiimTwL3txjXzZ3Pj/TDeyHXXa1joKm48vrOCeXatuor/+1vAi8vUaaVY6xvFT2sL9LTA9+Sfnin8rIXSWfsAGuAo/mLcxrYUmw7lbf7BnhgALHNAj8BZ/Pr/bx8HJjLX5g5YKLluF4Cvsr7PwZsK7bdk+vye+CpNuPK8y8Ah7q2a7q+3gZ+BP4hndFNAJPAZF4v4NUc9xxwV0v1dbW43gB+LY6vM3n5llxX5/LnPNVyXHuL4+sURYNWdQy0FVcu8yTpYZhyu6braxfpNtKXxWf14CCOMacGMTOzWq71PgwzM+sTNxhmZlaLGwwzM6vFDYaZmdXiBsPMzGpxg2HWg6QbJT1dzG+U9E5D+3qkzMpasf52SYeb2LdZXX6s1qyHnLfng4jY0cK+TpL+n+TiEmVmgT0RcaHpeMyq+ArDrLdDwEge42Ba0ubOWAlKY4K8J2lG0rykvUrjl3yRExx2xkkYkfRxTkr3qaRt3TuRtBW43GksJO3O4y2ck1TmI5ohZSMwGwg3GGa97QN+iIjRiHi+Yv0O4DFS+ooDwF8RMQZ8BjyRy7wOPBsRdwLPAa9VvM89pIR7HfuB+yJiJ/BwsfwMcO8K/h6zFbnWs9WaNelYpPEJLkn6nXQFACk1wx05u+g4cDQNsQKk3GTdNgC/FPMngMOSjgBlormfgY19jN/sf3GDYbZ8l4vpK8X8FdJ36zrgt4gYvcr7/E1KagdARExKupuUUO6spNFImWTX5LJmA+FbUma9XSINibkskcYsmJe0G/4bd3lnRdGvgVs6M5JGIuLziNgPXGQhPfVWoHK8abM2uMEw6yGf1Z/IHdDTy3ybx4EJSZ1MplVDih4HxrRw32pa0lzuYD9OyoIKaYz3D5cZh9mK+bFasyEg6RVgJiJme6xfDXwC7Io0lLBZ63yFYTYcDgLXL7F+E7DPjYUNkq8wzMysFl9hmJlZLW4wzMysFjcYZmZWixsMMzOrxQ2GmZnV8i96MwtLzc1frQAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "t = np.arange(0.0, 2.0, 0.01)\n", - "s = 1 + np.sin(2*np.pi*t)\n", - "plt.plot(t, s)\n", - "\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (mV)')\n", - "plt.title('About as simple as it gets, folks')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "jupytext": { - "formats": "ipynb,py:light" - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.6" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": {}, - "toc_section_display": true, - "toc_window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/demo/Paired Jupyter notebook and python script.py b/demo/Paired Jupyter notebook and python script.py deleted file mode 100644 index 572b708db..000000000 --- a/demo/Paired Jupyter notebook and python script.py +++ /dev/null @@ -1,49 +0,0 @@ -# --- -# jupyter: -# jupytext: -# formats: ipynb,py:light -# text_representation: -# extension: .py -# format_name: light -# format_version: '1.3' -# jupytext_version: 1.0.0-dev -# kernelspec: -# display_name: Python 3 -# language: python -# name: python3 -# --- - -# This is a notebook that you can use to experiment with the jupytext package. -# -# Proposed experimentations are -# 1. Open this Jupyter notebook (extension .ipynb) in Jupyter -# 2. Open the corresponding '.py' file. That is, copy the url for the notebook, that looks like -# ``` -# https://hub.mybinder.org/user/mwouts-jupytext-g7315gce/notebooks/demo/Sample%20notebook%20with%20python%20representation.ipynb -# ``` -# replace `/notebooks/` with `/edit/`, and change the extension from `ipynb` to `py`, to get an url like -# ``` -# https://hub.mybinder.org/user/mwouts-jupytext-g7315gce/edit/demo/Sample%20notebook%20with%20python%20representation.py -# ``` -# 3. Modify the notebook in Jupyter. Save. Refresh the python file in the editor, and observe the changes. -# 4. Now, modify the python file, save, and refresh the Jupyter notebook. Observe how inputs were updated, outputs preserved when possible, and kernel was left unchanged. -# 5. Browse the github repo using Jupyter in binder, and open arbitrary python files as notebooks. Run them when applicable. - -# %matplotlib inline - -# + -import matplotlib.pyplot as plt -import numpy as np - -t = np.arange(0.0, 2.0, 0.01) -s = 1 + np.sin(2*np.pi*t) -plt.plot(t, s) - -plt.xlabel('time (s)') -plt.ylabel('voltage (mV)') -plt.title('About as simple as it gets, folks') -# - - -plt.show() - - diff --git a/demo/World population.Rmd b/demo/World population.Rmd deleted file mode 100644 index f0f803077..000000000 --- a/demo/World population.Rmd +++ /dev/null @@ -1,113 +0,0 @@ ---- -jupyter: - jupytext: - cell_markers: region,endregion - formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc - text_representation: - extension: .Rmd - format_name: rmarkdown - format_version: '1.1' - jupytext_version: 1.1.0 - kernelspec: - display_name: Python 3 - language: python - name: python3 ---- - -# A quick insight at world population - -## Collecting population data - -In the below we retrieve population data from the -[World Bank](http://www.worldbank.org/) -using the [wbdata](https://github.com/OliverSherouse/wbdata) python package - -```{python} -import pandas as pd -import wbdata as wb - -pd.options.display.max_rows = 6 -pd.options.display.max_columns = 20 -``` - -Corresponding indicator is found using search method - or, directly, -the World Bank site. - -```{python} -wb.search_indicators('Population, total') # SP.POP.TOTL -# wb.search_indicators('area') -# => https://data.worldbank.org/indicator is easier to use -``` - -Now we download the population data - -```{python} -indicators = {'SP.POP.TOTL': 'Population, total', - 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', - 'AG.LND.TOTL.K2': 'Land area (sq. km)', - 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} -data = wb.get_dataframe(indicators, convert_date=True).sort_index() -data -``` - -World is one of the countries - -```{python} -data.loc['World'] -``` - -Can we classify over continents? - -```{python} -data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( -).sort_values().tail(60).index.get_level_values('country') -``` - -Extract zones manually (in order of increasing population) - -```{python} -zones = ['North America', 'Middle East & North Africa', - 'Latin America & Caribbean', 'Europe & Central Asia', - 'Sub-Saharan Africa', 'South Asia', - 'East Asia & Pacific'][::-1] -``` - -And extract population information (and check total is right) - -```{python} -population = data.loc[zones]['Population, total'].swaplevel().unstack() -population = population[zones] -assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) -``` - -## Stacked area plot with matplotlib - -```{python} -import matplotlib.pyplot as plt -``` - -```{python} -plt.clf() -plt.figure(figsize=(10, 5), dpi=100) -plt.stackplot(population.index, population.values.T / 1e9) -plt.legend(population.columns, loc='upper left') -plt.ylabel('Population count (B)') -plt.show() -``` - -## Stacked bar plot with plotly - -```{python} -import plotly.offline as offline -import plotly.graph_objs as go - -offline.init_notebook_mode() -``` - -```{python} -data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') - for zone in zones] -fig = go.Figure(data=data, - layout=go.Layout(title='World population')) -offline.iplot(fig) -``` diff --git a/demo/World population.lgt.py b/demo/World population.lgt.py deleted file mode 100644 index e485bb043..000000000 --- a/demo/World population.lgt.py +++ /dev/null @@ -1,95 +0,0 @@ -# --- -# jupyter: -# jupytext: -# cell_markers: region,endregion -# formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc -# text_representation: -# extension: .py -# format_name: light -# format_version: '1.4' -# jupytext_version: 1.1.0 -# kernelspec: -# display_name: Python 3 -# language: python -# name: python3 -# --- - -# # A quick insight at world population -# -# ## Collecting population data -# -# In the below we retrieve population data from the -# [World Bank](http://www.worldbank.org/) -# using the [wbdata](https://github.com/OliverSherouse/wbdata) python package - -# region -import pandas as pd -import wbdata as wb - -pd.options.display.max_rows = 6 -pd.options.display.max_columns = 20 -# endregion - -# Corresponding indicator is found using search method - or, directly, -# the World Bank site. - -wb.search_indicators('Population, total') # SP.POP.TOTL -# wb.search_indicators('area') -# => https://data.worldbank.org/indicator is easier to use - -# Now we download the population data - -indicators = {'SP.POP.TOTL': 'Population, total', - 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', - 'AG.LND.TOTL.K2': 'Land area (sq. km)', - 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} -data = wb.get_dataframe(indicators, convert_date=True).sort_index() -data - -# World is one of the countries - -data.loc['World'] - -# Can we classify over continents? - -data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( -).sort_values().tail(60).index.get_level_values('country') - -# Extract zones manually (in order of increasing population) - -zones = ['North America', 'Middle East & North Africa', - 'Latin America & Caribbean', 'Europe & Central Asia', - 'Sub-Saharan Africa', 'South Asia', - 'East Asia & Pacific'][::-1] - -# And extract population information (and check total is right) - -population = data.loc[zones]['Population, total'].swaplevel().unstack() -population = population[zones] -assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) - -# ## Stacked area plot with matplotlib - -import matplotlib.pyplot as plt - -plt.clf() -plt.figure(figsize=(10, 5), dpi=100) -plt.stackplot(population.index, population.values.T / 1e9) -plt.legend(population.columns, loc='upper left') -plt.ylabel('Population count (B)') -plt.show() - -# ## Stacked bar plot with plotly - -# region -import plotly.offline as offline -import plotly.graph_objs as go - -offline.init_notebook_mode() -# endregion - -data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') - for zone in zones] -fig = go.Figure(data=data, - layout=go.Layout(title='World population')) -offline.iplot(fig) diff --git a/demo/World population.md b/demo/World population.md deleted file mode 100644 index a11034039..000000000 --- a/demo/World population.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -jupyter: - jupytext: - cell_markers: region,endregion - formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc - text_representation: - extension: .md - format_name: markdown - format_version: '1.1' - jupytext_version: 1.1.0 - kernelspec: - display_name: Python 3 - language: python - name: python3 ---- - -# A quick insight at world population - -## Collecting population data - -In the below we retrieve population data from the -[World Bank](http://www.worldbank.org/) -using the [wbdata](https://github.com/OliverSherouse/wbdata) python package - -```python -import pandas as pd -import wbdata as wb - -pd.options.display.max_rows = 6 -pd.options.display.max_columns = 20 -``` - -Corresponding indicator is found using search method - or, directly, -the World Bank site. - -```python -wb.search_indicators('Population, total') # SP.POP.TOTL -# wb.search_indicators('area') -# => https://data.worldbank.org/indicator is easier to use -``` - -Now we download the population data - -```python -indicators = {'SP.POP.TOTL': 'Population, total', - 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', - 'AG.LND.TOTL.K2': 'Land area (sq. km)', - 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} -data = wb.get_dataframe(indicators, convert_date=True).sort_index() -data -``` - -World is one of the countries - -```python -data.loc['World'] -``` - -Can we classify over continents? - -```python -data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( -).sort_values().tail(60).index.get_level_values('country') -``` - -Extract zones manually (in order of increasing population) - -```python -zones = ['North America', 'Middle East & North Africa', - 'Latin America & Caribbean', 'Europe & Central Asia', - 'Sub-Saharan Africa', 'South Asia', - 'East Asia & Pacific'][::-1] -``` - -And extract population information (and check total is right) - -```python -population = data.loc[zones]['Population, total'].swaplevel().unstack() -population = population[zones] -assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) -``` - -## Stacked area plot with matplotlib - -```python -import matplotlib.pyplot as plt -``` - -```python -plt.clf() -plt.figure(figsize=(10, 5), dpi=100) -plt.stackplot(population.index, population.values.T / 1e9) -plt.legend(population.columns, loc='upper left') -plt.ylabel('Population count (B)') -plt.show() -``` - -## Stacked bar plot with plotly - -```python -import plotly.offline as offline -import plotly.graph_objs as go - -offline.init_notebook_mode() -``` - -```python -data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') - for zone in zones] -fig = go.Figure(data=data, - layout=go.Layout(title='World population')) -offline.iplot(fig) -``` diff --git a/demo/World population.pandoc.md b/demo/World population.pandoc.md deleted file mode 100644 index 87de7e280..000000000 --- a/demo/World population.pandoc.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -jupyter: - jupytext: - cell_markers: 'region,endregion' - formats: 'ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc' - text_representation: - extension: '.md' - format_name: pandoc - format_version: '2.7.2' - jupytext_version: '1.1.0' - kernelspec: - display_name: Python 3 - language: python - name: python3 - nbformat: 4 - nbformat_minor: 2 ---- - -::: {.cell .markdown} -# A quick insight at world population - -## Collecting population data - -In the below we retrieve population data from the -[World Bank](http://www.worldbank.org/) -using the [wbdata](https://github.com/OliverSherouse/wbdata) python package -::: - -::: {.cell .code} -``` {.python} -import pandas as pd -import wbdata as wb - -pd.options.display.max_rows = 6 -pd.options.display.max_columns = 20 -``` -::: - -::: {.cell .markdown} -Corresponding indicator is found using search method - or, directly, -the World Bank site. -::: - -::: {.cell .code} -``` {.python} -wb.search_indicators('Population, total') # SP.POP.TOTL -# wb.search_indicators('area') -# => https://data.worldbank.org/indicator is easier to use -``` -::: - -::: {.cell .markdown} -Now we download the population data -::: - -::: {.cell .code} -``` {.python} -indicators = {'SP.POP.TOTL': 'Population, total', - 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', - 'AG.LND.TOTL.K2': 'Land area (sq. km)', - 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} -data = wb.get_dataframe(indicators, convert_date=True).sort_index() -data -``` -::: - -::: {.cell .markdown} -World is one of the countries -::: - -::: {.cell .code} -``` {.python} -data.loc['World'] -``` -::: - -::: {.cell .markdown} -Can we classify over continents? -::: - -::: {.cell .code} -``` {.python} -data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( -).sort_values().tail(60).index.get_level_values('country') -``` -::: - -::: {.cell .markdown} -Extract zones manually (in order of increasing population) -::: - -::: {.cell .code} -``` {.python} -zones = ['North America', 'Middle East & North Africa', - 'Latin America & Caribbean', 'Europe & Central Asia', - 'Sub-Saharan Africa', 'South Asia', - 'East Asia & Pacific'][::-1] -``` -::: - -::: {.cell .markdown} -And extract population information (and check total is right) -::: - -::: {.cell .code} -``` {.python} -population = data.loc[zones]['Population, total'].swaplevel().unstack() -population = population[zones] -assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) -``` -::: - -::: {.cell .markdown} -## Stacked area plot with matplotlib -::: - -::: {.cell .code} -``` {.python} -import matplotlib.pyplot as plt -``` -::: - -::: {.cell .code} -``` {.python} -plt.clf() -plt.figure(figsize=(10, 5), dpi=100) -plt.stackplot(population.index, population.values.T / 1e9) -plt.legend(population.columns, loc='upper left') -plt.ylabel('Population count (B)') -plt.show() -``` -::: - -::: {.cell .markdown} -## Stacked bar plot with plotly -::: - -::: {.cell .code} -``` {.python} -import plotly.offline as offline -import plotly.graph_objs as go - -offline.init_notebook_mode() -``` -::: - -::: {.cell .code} -``` {.python} -data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') - for zone in zones] -fig = go.Figure(data=data, - layout=go.Layout(title='World population')) -offline.iplot(fig) -``` -::: diff --git a/demo/World population.pct.py b/demo/World population.pct.py deleted file mode 100644 index f74c8eee5..000000000 --- a/demo/World population.pct.py +++ /dev/null @@ -1,111 +0,0 @@ -# --- -# jupyter: -# jupytext: -# cell_markers: region,endregion -# formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc -# text_representation: -# extension: .py -# format_name: percent -# format_version: '1.2' -# jupytext_version: 1.1.0 -# kernelspec: -# display_name: Python 3 -# language: python -# name: python3 -# --- - -# %% [markdown] -# # A quick insight at world population -# -# ## Collecting population data -# -# In the below we retrieve population data from the -# [World Bank](http://www.worldbank.org/) -# using the [wbdata](https://github.com/OliverSherouse/wbdata) python package - -# %% -import pandas as pd -import wbdata as wb - -pd.options.display.max_rows = 6 -pd.options.display.max_columns = 20 - -# %% [markdown] -# Corresponding indicator is found using search method - or, directly, -# the World Bank site. - -# %% -wb.search_indicators('Population, total') # SP.POP.TOTL -# wb.search_indicators('area') -# => https://data.worldbank.org/indicator is easier to use - -# %% [markdown] -# Now we download the population data - -# %% -indicators = {'SP.POP.TOTL': 'Population, total', - 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', - 'AG.LND.TOTL.K2': 'Land area (sq. km)', - 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} -data = wb.get_dataframe(indicators, convert_date=True).sort_index() -data - -# %% [markdown] -# World is one of the countries - -# %% -data.loc['World'] - -# %% [markdown] -# Can we classify over continents? - -# %% -data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( -).sort_values().tail(60).index.get_level_values('country') - -# %% [markdown] -# Extract zones manually (in order of increasing population) - -# %% -zones = ['North America', 'Middle East & North Africa', - 'Latin America & Caribbean', 'Europe & Central Asia', - 'Sub-Saharan Africa', 'South Asia', - 'East Asia & Pacific'][::-1] - -# %% [markdown] -# And extract population information (and check total is right) - -# %% -population = data.loc[zones]['Population, total'].swaplevel().unstack() -population = population[zones] -assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) - -# %% [markdown] -# ## Stacked area plot with matplotlib - -# %% -import matplotlib.pyplot as plt - -# %% -plt.clf() -plt.figure(figsize=(10, 5), dpi=100) -plt.stackplot(population.index, population.values.T / 1e9) -plt.legend(population.columns, loc='upper left') -plt.ylabel('Population count (B)') -plt.show() - -# %% [markdown] -# ## Stacked bar plot with plotly - -# %% -import plotly.offline as offline -import plotly.graph_objs as go - -offline.init_notebook_mode() - -# %% -data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') - for zone in zones] -fig = go.Figure(data=data, - layout=go.Layout(title='World population')) -offline.iplot(fig) diff --git a/demo/World population.spx.py b/demo/World population.spx.py deleted file mode 100644 index 9fe5da91b..000000000 --- a/demo/World population.spx.py +++ /dev/null @@ -1,103 +0,0 @@ -# --- -# jupyter: -# jupytext: -# cell_markers: region,endregion -# formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc -# text_representation: -# extension: .py -# format_name: sphinx -# format_version: '1.1' -# jupytext_version: 1.1.0 -# kernelspec: -# display_name: Python 3 -# language: python -# name: python3 -# --- - -""" -# A quick insight at world population - -## Collecting population data - -In the below we retrieve population data from the -[World Bank](http://www.worldbank.org/) -using the [wbdata](https://github.com/OliverSherouse/wbdata) python package -""" - -import pandas as pd -import wbdata as wb - -pd.options.display.max_rows = 6 -pd.options.display.max_columns = 20 - -############################################################################### -# Corresponding indicator is found using search method - or, directly, -# the World Bank site. - -wb.search_indicators('Population, total') # SP.POP.TOTL -# wb.search_indicators('area') -# => https://data.worldbank.org/indicator is easier to use - -############################################################################### -# Now we download the population data - -indicators = {'SP.POP.TOTL': 'Population, total', - 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', - 'AG.LND.TOTL.K2': 'Land area (sq. km)', - 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} -data = wb.get_dataframe(indicators, convert_date=True).sort_index() -data - -############################################################################### -# World is one of the countries - -data.loc['World'] - -############################################################################### -# Can we classify over continents? - -data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( -).sort_values().tail(60).index.get_level_values('country') - -############################################################################### -# Extract zones manually (in order of increasing population) - -zones = ['North America', 'Middle East & North Africa', - 'Latin America & Caribbean', 'Europe & Central Asia', - 'Sub-Saharan Africa', 'South Asia', - 'East Asia & Pacific'][::-1] - -############################################################################### -# And extract population information (and check total is right) - -population = data.loc[zones]['Population, total'].swaplevel().unstack() -population = population[zones] -assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) - -############################################################################### -# ## Stacked area plot with matplotlib - -import matplotlib.pyplot as plt - -"" -plt.clf() -plt.figure(figsize=(10, 5), dpi=100) -plt.stackplot(population.index, population.values.T / 1e9) -plt.legend(population.columns, loc='upper left') -plt.ylabel('Population count (B)') -plt.show() - -############################################################################### -# ## Stacked bar plot with plotly - -import plotly.offline as offline -import plotly.graph_objs as go - -offline.init_notebook_mode() - -"" -data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') - for zone in zones] -fig = go.Figure(data=data, - layout=go.Layout(title='World population')) -offline.iplot(fig) diff --git a/demo/get_started.ipynb b/demo/get_started.ipynb deleted file mode 100644 index d7bdb8348..000000000 --- a/demo/get_started.ipynb +++ /dev/null @@ -1,119 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting started with Jupytext\n", - "\n", - "This small notebook shows you how to activate Jupytext in the JupyterLab\n", - "environment. We'll show you a few things that you can do with Jupytext and\n", - "a bit of what happens under the hood.\n", - "\n", - "**Note: to run this notebook locally, you need to first follow the Jupytext\n", - "installation instructions and activate the JupyterLab plugin. If you're on\n", - "Binder, it should already work.**\n", - "\n", - "## Enabling Jupytext in a new notebook\n", - "\n", - "This notebook is brand new - it hasn't had any special extra metadata added\n", - "to it. \n", - "\n", - "If we want Jupytext to save files in multiple formats automatically,\n", - "we can use the JupyterLab **command palette** to do so.\n", - "\n", - "* Click on the little 🎨 icon to the left\n", - "* Then type **`Jupytext`**. You should see a number of commands come up. Each\n", - " one tells Jupytext to save the notebook in a different\n", - " file format automatically.\n", - "* Select **Pair notebook with Markdown**\n", - "\n", - "That's it! If you have Jupytext installed, it will now save your notebook in\n", - "markdown format automatically when you save this `.ipynb` file.\n", - "\n", - "After you've done this, save the notebook. You should now see a new file called\n", - "**`get_started.md`** in the same directory as this notebook.\n", - "\n", - "## How does Jupytext know to do this?\n", - "\n", - "Jupytext uses notebook-level metadata to keep track of what languages are paired\n", - "with a notebook. Below we'll print the metadata of this notebook so you can see\n", - "what the Jupytext metadata looks like." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import nbformat as nbf\n", - "from IPython.display import JSON\n", - "notebook = nbf.read('./get_started.ipynb', nbf.NO_CONVERT)\n", - "JSON(notebook['metadata'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As you select different languages from the command palette (following the instructions\n", - "above) and save the notebook, you'll see this metadata change." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## That's it!\n", - "\n", - "Play around with different kinds of code and outputs to see how each is\n", - "converted into its corresponding text format. Here's a little Python code\n", - "to get you started:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "plt.scatter(*np.random.randn(2, 100), c=np.random.randn(100), s=np.random.rand(100)*100)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Experiment with other notebooks\n", - "\n", - "There are several other demo notebooks for you to explore Jupytext's functionality,\n", - "try them out!" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/demo/get_started.md b/demo/get_started.md new file mode 100644 index 000000000..861742836 --- /dev/null +++ b/demo/get_started.md @@ -0,0 +1,81 @@ +--- +jupyter: + jupytext: + formats: ipynb,md + text_representation: + extension: .md + format_name: markdown + format_version: '1.1' + jupytext_version: 1.1.6 + kernelspec: + display_name: Python 3 + language: python + name: python3 +--- + +# Getting started with Jupytext + +This small notebook shows you how to activate Jupytext in the JupyterLab +environment. We'll show you a few things that you can do with Jupytext and +a bit of what happens under the hood. + +**Note: to run this notebook locally, you need to first follow the Jupytext +installation instructions and activate the JupyterLab plugin. If you're on +Binder, it should already work.** + +## Enabling Jupytext in a new notebook + +This notebook is brand new - it hasn't had any special extra metadata added +to it. + +If we want Jupytext to save files in multiple formats automatically, +we can use the JupyterLab **command palette** to do so. + +* Click on the little 🎨 icon to the left +* Then type **`Jupytext`**. You should see a number of commands come up. Each + one tells Jupytext to save the notebook in a different + file format automatically. +* Select **Pair notebook with Markdown** + +That's it! If you have Jupytext installed, it will now save your notebook in +markdown format automatically when you save this `.ipynb` file +**in addition to** saving the `.ipynb` file itself. + +After you've done this, save the notebook. You should now see a new file called +**`get_started.md`** in the same directory as this notebook. + +## How does Jupytext know to do this? + +Jupytext uses notebook-level metadata to keep track of what languages are paired +with a notebook. Below we'll print the metadata of this notebook so you can see +what the Jupytext metadata looks like. + +```python +import nbformat as nbf +from IPython.display import JSON +notebook = nbf.read('./get_started.ipynb', nbf.NO_CONVERT) +JSON(notebook['metadata']) +``` + +As you select different languages from the command palette (following the instructions +above) and save the notebook, you'll see this metadata change. + + +## That's it! + +Play around with different kinds of code and outputs to see how each is +converted into its corresponding text format. Here's a little Python code +to get you started: + +```python +import numpy as np +import matplotlib.pyplot as plt + +plt.scatter(*np.random.randn(2, 100), c=np.random.randn(100), s=np.random.rand(100)*100) +``` + +# Experiment with the demo notebook! + +In the "demo" folder for `jupytext` there is a notebook called **`World population.ipynb`**. +By default, saving the demo notebook will also create *many* possible Jupytext +outputs so you can see what each looks like and which you prefer. diff --git a/demo/sample_python_script.py b/demo/sample_python_script.py deleted file mode 100644 index 6739ddd25..000000000 --- a/demo/sample_python_script.py +++ /dev/null @@ -1,33 +0,0 @@ -import math - - -# # A recursive implementation of the factorial - -def factorial(n): - if n <= 1: - return n - return n * factorial(n - 1) - - -factorial(5) - -factorial(12) - -# Python has great support for large integers: - -factorial(120) - -# We run into troubles with large recursions! - -factorial(5000) - - -# # Stirling's approximation of n! - -def stirling_formula(x): - return math.sqrt(2.0 * math.pi * x) * math.pow(x / math.e, x) - - -# Not so bad in practice: - -factorial(120) / stirling_formula(120) From af70905082f062f5a31b2ab2b02f41202d2f4eec Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 20 Jun 2019 12:10:05 -0700 Subject: [PATCH 5/7] adding back in world population and small edits --- .gitignore | 9 -- demo/World population.Rmd | 113 +++++++++++++++++++++++ demo/World population.lgt.py | 95 ++++++++++++++++++++ demo/World population.md | 113 +++++++++++++++++++++++ demo/World population.pandoc.md | 155 ++++++++++++++++++++++++++++++++ demo/World population.pct.py | 111 +++++++++++++++++++++++ demo/World population.spx.py | 103 +++++++++++++++++++++ demo/get_started.md | 8 +- docs/formats.md | 8 +- 9 files changed, 698 insertions(+), 17 deletions(-) create mode 100644 demo/World population.Rmd create mode 100644 demo/World population.lgt.py create mode 100644 demo/World population.md create mode 100644 demo/World population.pandoc.md create mode 100644 demo/World population.pct.py create mode 100644 demo/World population.spx.py diff --git a/.gitignore b/.gitignore index 93c5fd0db..de12557a4 100644 --- a/.gitignore +++ b/.gitignore @@ -17,12 +17,3 @@ docs/_build # Will be created by postBuild demo/get_started.ipynb - -# Files that will be created by saving the World population notebook -demo/Paired Jupyter notebook and python script.py -demo/World population.Rmd -demo/World population.lgt.py -demo/World population.md -demo/World population.pandoc.md -demo/World population.pct.py -demo/World population.spx.py \ No newline at end of file diff --git a/demo/World population.Rmd b/demo/World population.Rmd new file mode 100644 index 000000000..f0f803077 --- /dev/null +++ b/demo/World population.Rmd @@ -0,0 +1,113 @@ +--- +jupyter: + jupytext: + cell_markers: region,endregion + formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc + text_representation: + extension: .Rmd + format_name: rmarkdown + format_version: '1.1' + jupytext_version: 1.1.0 + kernelspec: + display_name: Python 3 + language: python + name: python3 +--- + +# A quick insight at world population + +## Collecting population data + +In the below we retrieve population data from the +[World Bank](http://www.worldbank.org/) +using the [wbdata](https://github.com/OliverSherouse/wbdata) python package + +```{python} +import pandas as pd +import wbdata as wb + +pd.options.display.max_rows = 6 +pd.options.display.max_columns = 20 +``` + +Corresponding indicator is found using search method - or, directly, +the World Bank site. + +```{python} +wb.search_indicators('Population, total') # SP.POP.TOTL +# wb.search_indicators('area') +# => https://data.worldbank.org/indicator is easier to use +``` + +Now we download the population data + +```{python} +indicators = {'SP.POP.TOTL': 'Population, total', + 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', + 'AG.LND.TOTL.K2': 'Land area (sq. km)', + 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} +data = wb.get_dataframe(indicators, convert_date=True).sort_index() +data +``` + +World is one of the countries + +```{python} +data.loc['World'] +``` + +Can we classify over continents? + +```{python} +data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( +).sort_values().tail(60).index.get_level_values('country') +``` + +Extract zones manually (in order of increasing population) + +```{python} +zones = ['North America', 'Middle East & North Africa', + 'Latin America & Caribbean', 'Europe & Central Asia', + 'Sub-Saharan Africa', 'South Asia', + 'East Asia & Pacific'][::-1] +``` + +And extract population information (and check total is right) + +```{python} +population = data.loc[zones]['Population, total'].swaplevel().unstack() +population = population[zones] +assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) +``` + +## Stacked area plot with matplotlib + +```{python} +import matplotlib.pyplot as plt +``` + +```{python} +plt.clf() +plt.figure(figsize=(10, 5), dpi=100) +plt.stackplot(population.index, population.values.T / 1e9) +plt.legend(population.columns, loc='upper left') +plt.ylabel('Population count (B)') +plt.show() +``` + +## Stacked bar plot with plotly + +```{python} +import plotly.offline as offline +import plotly.graph_objs as go + +offline.init_notebook_mode() +``` + +```{python} +data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') + for zone in zones] +fig = go.Figure(data=data, + layout=go.Layout(title='World population')) +offline.iplot(fig) +``` diff --git a/demo/World population.lgt.py b/demo/World population.lgt.py new file mode 100644 index 000000000..e485bb043 --- /dev/null +++ b/demo/World population.lgt.py @@ -0,0 +1,95 @@ +# --- +# jupyter: +# jupytext: +# cell_markers: region,endregion +# formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.4' +# jupytext_version: 1.1.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# # A quick insight at world population +# +# ## Collecting population data +# +# In the below we retrieve population data from the +# [World Bank](http://www.worldbank.org/) +# using the [wbdata](https://github.com/OliverSherouse/wbdata) python package + +# region +import pandas as pd +import wbdata as wb + +pd.options.display.max_rows = 6 +pd.options.display.max_columns = 20 +# endregion + +# Corresponding indicator is found using search method - or, directly, +# the World Bank site. + +wb.search_indicators('Population, total') # SP.POP.TOTL +# wb.search_indicators('area') +# => https://data.worldbank.org/indicator is easier to use + +# Now we download the population data + +indicators = {'SP.POP.TOTL': 'Population, total', + 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', + 'AG.LND.TOTL.K2': 'Land area (sq. km)', + 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} +data = wb.get_dataframe(indicators, convert_date=True).sort_index() +data + +# World is one of the countries + +data.loc['World'] + +# Can we classify over continents? + +data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( +).sort_values().tail(60).index.get_level_values('country') + +# Extract zones manually (in order of increasing population) + +zones = ['North America', 'Middle East & North Africa', + 'Latin America & Caribbean', 'Europe & Central Asia', + 'Sub-Saharan Africa', 'South Asia', + 'East Asia & Pacific'][::-1] + +# And extract population information (and check total is right) + +population = data.loc[zones]['Population, total'].swaplevel().unstack() +population = population[zones] +assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) + +# ## Stacked area plot with matplotlib + +import matplotlib.pyplot as plt + +plt.clf() +plt.figure(figsize=(10, 5), dpi=100) +plt.stackplot(population.index, population.values.T / 1e9) +plt.legend(population.columns, loc='upper left') +plt.ylabel('Population count (B)') +plt.show() + +# ## Stacked bar plot with plotly + +# region +import plotly.offline as offline +import plotly.graph_objs as go + +offline.init_notebook_mode() +# endregion + +data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') + for zone in zones] +fig = go.Figure(data=data, + layout=go.Layout(title='World population')) +offline.iplot(fig) diff --git a/demo/World population.md b/demo/World population.md new file mode 100644 index 000000000..a11034039 --- /dev/null +++ b/demo/World population.md @@ -0,0 +1,113 @@ +--- +jupyter: + jupytext: + cell_markers: region,endregion + formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc + text_representation: + extension: .md + format_name: markdown + format_version: '1.1' + jupytext_version: 1.1.0 + kernelspec: + display_name: Python 3 + language: python + name: python3 +--- + +# A quick insight at world population + +## Collecting population data + +In the below we retrieve population data from the +[World Bank](http://www.worldbank.org/) +using the [wbdata](https://github.com/OliverSherouse/wbdata) python package + +```python +import pandas as pd +import wbdata as wb + +pd.options.display.max_rows = 6 +pd.options.display.max_columns = 20 +``` + +Corresponding indicator is found using search method - or, directly, +the World Bank site. + +```python +wb.search_indicators('Population, total') # SP.POP.TOTL +# wb.search_indicators('area') +# => https://data.worldbank.org/indicator is easier to use +``` + +Now we download the population data + +```python +indicators = {'SP.POP.TOTL': 'Population, total', + 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', + 'AG.LND.TOTL.K2': 'Land area (sq. km)', + 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} +data = wb.get_dataframe(indicators, convert_date=True).sort_index() +data +``` + +World is one of the countries + +```python +data.loc['World'] +``` + +Can we classify over continents? + +```python +data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( +).sort_values().tail(60).index.get_level_values('country') +``` + +Extract zones manually (in order of increasing population) + +```python +zones = ['North America', 'Middle East & North Africa', + 'Latin America & Caribbean', 'Europe & Central Asia', + 'Sub-Saharan Africa', 'South Asia', + 'East Asia & Pacific'][::-1] +``` + +And extract population information (and check total is right) + +```python +population = data.loc[zones]['Population, total'].swaplevel().unstack() +population = population[zones] +assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) +``` + +## Stacked area plot with matplotlib + +```python +import matplotlib.pyplot as plt +``` + +```python +plt.clf() +plt.figure(figsize=(10, 5), dpi=100) +plt.stackplot(population.index, population.values.T / 1e9) +plt.legend(population.columns, loc='upper left') +plt.ylabel('Population count (B)') +plt.show() +``` + +## Stacked bar plot with plotly + +```python +import plotly.offline as offline +import plotly.graph_objs as go + +offline.init_notebook_mode() +``` + +```python +data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') + for zone in zones] +fig = go.Figure(data=data, + layout=go.Layout(title='World population')) +offline.iplot(fig) +``` diff --git a/demo/World population.pandoc.md b/demo/World population.pandoc.md new file mode 100644 index 000000000..87de7e280 --- /dev/null +++ b/demo/World population.pandoc.md @@ -0,0 +1,155 @@ +--- +jupyter: + jupytext: + cell_markers: 'region,endregion' + formats: 'ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc' + text_representation: + extension: '.md' + format_name: pandoc + format_version: '2.7.2' + jupytext_version: '1.1.0' + kernelspec: + display_name: Python 3 + language: python + name: python3 + nbformat: 4 + nbformat_minor: 2 +--- + +::: {.cell .markdown} +# A quick insight at world population + +## Collecting population data + +In the below we retrieve population data from the +[World Bank](http://www.worldbank.org/) +using the [wbdata](https://github.com/OliverSherouse/wbdata) python package +::: + +::: {.cell .code} +``` {.python} +import pandas as pd +import wbdata as wb + +pd.options.display.max_rows = 6 +pd.options.display.max_columns = 20 +``` +::: + +::: {.cell .markdown} +Corresponding indicator is found using search method - or, directly, +the World Bank site. +::: + +::: {.cell .code} +``` {.python} +wb.search_indicators('Population, total') # SP.POP.TOTL +# wb.search_indicators('area') +# => https://data.worldbank.org/indicator is easier to use +``` +::: + +::: {.cell .markdown} +Now we download the population data +::: + +::: {.cell .code} +``` {.python} +indicators = {'SP.POP.TOTL': 'Population, total', + 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', + 'AG.LND.TOTL.K2': 'Land area (sq. km)', + 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} +data = wb.get_dataframe(indicators, convert_date=True).sort_index() +data +``` +::: + +::: {.cell .markdown} +World is one of the countries +::: + +::: {.cell .code} +``` {.python} +data.loc['World'] +``` +::: + +::: {.cell .markdown} +Can we classify over continents? +::: + +::: {.cell .code} +``` {.python} +data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( +).sort_values().tail(60).index.get_level_values('country') +``` +::: + +::: {.cell .markdown} +Extract zones manually (in order of increasing population) +::: + +::: {.cell .code} +``` {.python} +zones = ['North America', 'Middle East & North Africa', + 'Latin America & Caribbean', 'Europe & Central Asia', + 'Sub-Saharan Africa', 'South Asia', + 'East Asia & Pacific'][::-1] +``` +::: + +::: {.cell .markdown} +And extract population information (and check total is right) +::: + +::: {.cell .code} +``` {.python} +population = data.loc[zones]['Population, total'].swaplevel().unstack() +population = population[zones] +assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) +``` +::: + +::: {.cell .markdown} +## Stacked area plot with matplotlib +::: + +::: {.cell .code} +``` {.python} +import matplotlib.pyplot as plt +``` +::: + +::: {.cell .code} +``` {.python} +plt.clf() +plt.figure(figsize=(10, 5), dpi=100) +plt.stackplot(population.index, population.values.T / 1e9) +plt.legend(population.columns, loc='upper left') +plt.ylabel('Population count (B)') +plt.show() +``` +::: + +::: {.cell .markdown} +## Stacked bar plot with plotly +::: + +::: {.cell .code} +``` {.python} +import plotly.offline as offline +import plotly.graph_objs as go + +offline.init_notebook_mode() +``` +::: + +::: {.cell .code} +``` {.python} +data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') + for zone in zones] +fig = go.Figure(data=data, + layout=go.Layout(title='World population')) +offline.iplot(fig) +``` +::: diff --git a/demo/World population.pct.py b/demo/World population.pct.py new file mode 100644 index 000000000..f74c8eee5 --- /dev/null +++ b/demo/World population.pct.py @@ -0,0 +1,111 @@ +# --- +# jupyter: +# jupytext: +# cell_markers: region,endregion +# formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.2' +# jupytext_version: 1.1.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# %% [markdown] +# # A quick insight at world population +# +# ## Collecting population data +# +# In the below we retrieve population data from the +# [World Bank](http://www.worldbank.org/) +# using the [wbdata](https://github.com/OliverSherouse/wbdata) python package + +# %% +import pandas as pd +import wbdata as wb + +pd.options.display.max_rows = 6 +pd.options.display.max_columns = 20 + +# %% [markdown] +# Corresponding indicator is found using search method - or, directly, +# the World Bank site. + +# %% +wb.search_indicators('Population, total') # SP.POP.TOTL +# wb.search_indicators('area') +# => https://data.worldbank.org/indicator is easier to use + +# %% [markdown] +# Now we download the population data + +# %% +indicators = {'SP.POP.TOTL': 'Population, total', + 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', + 'AG.LND.TOTL.K2': 'Land area (sq. km)', + 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} +data = wb.get_dataframe(indicators, convert_date=True).sort_index() +data + +# %% [markdown] +# World is one of the countries + +# %% +data.loc['World'] + +# %% [markdown] +# Can we classify over continents? + +# %% +data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( +).sort_values().tail(60).index.get_level_values('country') + +# %% [markdown] +# Extract zones manually (in order of increasing population) + +# %% +zones = ['North America', 'Middle East & North Africa', + 'Latin America & Caribbean', 'Europe & Central Asia', + 'Sub-Saharan Africa', 'South Asia', + 'East Asia & Pacific'][::-1] + +# %% [markdown] +# And extract population information (and check total is right) + +# %% +population = data.loc[zones]['Population, total'].swaplevel().unstack() +population = population[zones] +assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) + +# %% [markdown] +# ## Stacked area plot with matplotlib + +# %% +import matplotlib.pyplot as plt + +# %% +plt.clf() +plt.figure(figsize=(10, 5), dpi=100) +plt.stackplot(population.index, population.values.T / 1e9) +plt.legend(population.columns, loc='upper left') +plt.ylabel('Population count (B)') +plt.show() + +# %% [markdown] +# ## Stacked bar plot with plotly + +# %% +import plotly.offline as offline +import plotly.graph_objs as go + +offline.init_notebook_mode() + +# %% +data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') + for zone in zones] +fig = go.Figure(data=data, + layout=go.Layout(title='World population')) +offline.iplot(fig) diff --git a/demo/World population.spx.py b/demo/World population.spx.py new file mode 100644 index 000000000..9fe5da91b --- /dev/null +++ b/demo/World population.spx.py @@ -0,0 +1,103 @@ +# --- +# jupyter: +# jupytext: +# cell_markers: region,endregion +# formats: ipynb,.pct.py:percent,.lgt.py:light,.spx.py:sphinx,md,Rmd,.pandoc.md:pandoc +# text_representation: +# extension: .py +# format_name: sphinx +# format_version: '1.1' +# jupytext_version: 1.1.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +""" +# A quick insight at world population + +## Collecting population data + +In the below we retrieve population data from the +[World Bank](http://www.worldbank.org/) +using the [wbdata](https://github.com/OliverSherouse/wbdata) python package +""" + +import pandas as pd +import wbdata as wb + +pd.options.display.max_rows = 6 +pd.options.display.max_columns = 20 + +############################################################################### +# Corresponding indicator is found using search method - or, directly, +# the World Bank site. + +wb.search_indicators('Population, total') # SP.POP.TOTL +# wb.search_indicators('area') +# => https://data.worldbank.org/indicator is easier to use + +############################################################################### +# Now we download the population data + +indicators = {'SP.POP.TOTL': 'Population, total', + 'AG.SRF.TOTL.K2': 'Surface area (sq. km)', + 'AG.LND.TOTL.K2': 'Land area (sq. km)', + 'AG.LND.ARBL.ZS': 'Arable land (% of land area)'} +data = wb.get_dataframe(indicators, convert_date=True).sort_index() +data + +############################################################################### +# World is one of the countries + +data.loc['World'] + +############################################################################### +# Can we classify over continents? + +data.loc[(slice(None), '2017-01-01'), :]['Population, total'].dropna( +).sort_values().tail(60).index.get_level_values('country') + +############################################################################### +# Extract zones manually (in order of increasing population) + +zones = ['North America', 'Middle East & North Africa', + 'Latin America & Caribbean', 'Europe & Central Asia', + 'Sub-Saharan Africa', 'South Asia', + 'East Asia & Pacific'][::-1] + +############################################################################### +# And extract population information (and check total is right) + +population = data.loc[zones]['Population, total'].swaplevel().unstack() +population = population[zones] +assert all(data.loc['World']['Population, total'] == population.sum(axis=1)) + +############################################################################### +# ## Stacked area plot with matplotlib + +import matplotlib.pyplot as plt + +"" +plt.clf() +plt.figure(figsize=(10, 5), dpi=100) +plt.stackplot(population.index, population.values.T / 1e9) +plt.legend(population.columns, loc='upper left') +plt.ylabel('Population count (B)') +plt.show() + +############################################################################### +# ## Stacked bar plot with plotly + +import plotly.offline as offline +import plotly.graph_objs as go + +offline.init_notebook_mode() + +"" +data = [go.Scatter(x=population.index, y=population[zone], name=zone, stackgroup='World') + for zone in zones] +fig = go.Figure(data=data, + layout=go.Layout(title='World population')) +offline.iplot(fig) diff --git a/demo/get_started.md b/demo/get_started.md index 861742836..765f0c9e5 100644 --- a/demo/get_started.md +++ b/demo/get_started.md @@ -26,7 +26,7 @@ Binder, it should already work.** ## Enabling Jupytext in a new notebook This notebook is brand new - it hasn't had any special extra metadata added -to it. +to it. If we want Jupytext to save files in multiple formats automatically, we can use the JupyterLab **command palette** to do so. @@ -46,7 +46,7 @@ After you've done this, save the notebook. You should now see a new file called ## How does Jupytext know to do this? -Jupytext uses notebook-level metadata to keep track of what languages are paired +Jupytext uses notebook-level metadata to keep track of what formats are paired with a notebook. Below we'll print the metadata of this notebook so you can see what the Jupytext metadata looks like. @@ -57,7 +57,7 @@ notebook = nbf.read('./get_started.ipynb', nbf.NO_CONVERT) JSON(notebook['metadata']) ``` -As you select different languages from the command palette (following the instructions +As you select different formats from the command palette (following the instructions above) and save the notebook, you'll see this metadata change. @@ -78,4 +78,4 @@ plt.scatter(*np.random.randn(2, 100), c=np.random.randn(100), s=np.random.rand(1 In the "demo" folder for `jupytext` there is a notebook called **`World population.ipynb`**. By default, saving the demo notebook will also create *many* possible Jupytext -outputs so you can see what each looks like and which you prefer. +outputs so you can see what each looks like and which you prefer. diff --git a/docs/formats.md b/docs/formats.md index bf090d820..c6366dd8f 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -25,14 +25,14 @@ c.ContentsManager.split_at_heading = True ## Pandoc's Markdown -Pandoc, the _Universal document converter_, can now read and write Jupyter notebooks - see [Pandoc's documentation](https://pandoc.org/MANUAL.html#creating-jupyter-notebooks-with-pandoc). +Pandoc, the _Universal document converter_, can now read and write Jupyter notebooks - see [Pandoc's documentation](https://pandoc.org/MANUAL.html#creating-jupyter-notebooks-with-pandoc). Pandoc's Markdown format is available in Jupytext as `md:pandoc`. This requires `pandoc` in version 2.7.2 or above - please check Pandoc's version number with `pandoc -v` before running either `jupytext` command line, or before you start your Jupyter notebook or Lab server. Note that you can get the latest version of `pandoc` in a conda environment with ``` conda install pandoc -c conda-forge ``` -Pandoc's format uses Pandoc divs (`:::`) as explicit cell markers. See how our `World population.ipynb` notebook is [represented](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.pandoc.md) in that format. Please also note that `pandoc`, while preserving the HTML rendering, may reformat the text in some of the Markdown cells. If that is an issue for you, please wait until [jgm/pandoc#5408](https://github.com/jgm/pandoc/issues/5408) gets implemented. +Pandoc's format uses Pandoc divs (`:::`) as explicit cell markers. See how our `World population.ipynb` notebook is [represented](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.pandoc.md#a-quick-insight-at-world-population) in that format. Please also note that `pandoc`, while preserving the HTML rendering, may reformat the text in some of the Markdown cells. If that is an issue for you, please wait until [jgm/pandoc#5408](https://github.com/jgm/pandoc/issues/5408) gets implemented. Jupytext currently strips the output cells before calling `pandoc`. As for the other formats, outputs cells can be preserved in paired notebooks. In the case of the pandoc format, paired notebooks are available with the metadata `"jupytext": {"formats": "md:pandoc,ipynb"}`. @@ -48,13 +48,13 @@ The `light` format has: The `light` format is available for these [languages](https://github.com/mwouts/jupytext/blob/master/jupytext/languages.py). Open our sample notebook in the `light` format [here](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.lgt.py). -A variation of the `light` format is the `bare` format, with no cell marker at all. Please note that this format will split your code cells on code paragraphs. By default, this format still includes a YAML header - if you prefer to also remove the header, set `"notebook_metadata_filter": "-all"` in the jupytext section of your notebook metadata. +A variation of the `light` format is the `bare` format, with no cell marker at all. Please note that this format will split your code cells on code paragraphs. By default, this format still includes a YAML header - if you prefer to also remove the header, set `"notebook_metadata_filter": "-all"` in the jupytext section of your notebook metadata. The `light` format can use custom cell markers instead of `# +` or `# -`. If you prefer to mark cells with VScode/PyCharm (resp. Vim) folding markers, set `"cell_markers": "region,endregion"` (resp. `"{{{,}}}"`) in the jupytext section of the notebook metadata. If you want to configure this as a global default, add either ```python c.ContentsManager.default_cell_markers = "region,endregion" # Use VScode/PyCharm region folding delimiters ``` -or +or ```python c.ContentsManager.default_cell_markers = "{{{,}}}" # Use Vim region folding delimiters ``` From c1b802c0a6d6a80935606af60cbaa852662667f6 Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Thu, 20 Jun 2019 22:08:39 +0200 Subject: [PATCH 6/7] Links to .md files require # on Sphinx Fix #255 --- docs/formats.md | 4 ++-- docs/introduction.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/formats.md b/docs/formats.md index c6366dd8f..817fe5705 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -15,7 +15,7 @@ Jupytext's implementation for Jupyter notebooks as [Markdown](https://daringfire - Code and raw cells are encoded as Markdown code blocks with triple backticks. In a Python notebook, a code cell starts with ` ```python` and ends with ` ``` `. Cell metadata are found after the language information, with a `key=value` syntax, where `value` is encoded in JSON format (Markdown) or R format (R Markdown). R Markdown [code cell options](https://yihui.name/knitr/options/) are mapped to the corresponding Jupyter cell metadata options, when available. - Markdown cells are inserted verbatim and separated with two blank lines. When required (cells with metadata, cells that contain two blank lines or code blocks), Jupytext protects the cell boundary with HTML comments: `` and ``. Cells with explicit boundaries are [foldable](https://code.visualstudio.com/docs/editor/codebasics#_folding) in vscode, and can accept both a title and/or metadata in JSON format: ``. -See how our `World population.ipynb` notebook in the [demo folder](https://github.com/mwouts/jupytext/tree/master/demo) is represented in [Markdown](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.md) or [R Markdown](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.Rmd). +See how our `World population.ipynb` notebook in the [demo folder](https://github.com/mwouts/jupytext/tree/master/demo) is represented in [Markdown](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.md#) or [R Markdown](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.Rmd). When you open a plain Markdown file in Jupytext, the Markdown text is rendered in Markdown cells. Cells breaks occur when the text contains two consecutive blank lines (or code cells). If you want to also split cells on Markdown headers, so that headers prefixed by one blank line appear at the top of a new cell, use the `split_at_heading` option. Set the option either on the command line, or by adding `"split_at_heading": true` to the jupytext section in the notebook metadata, or on Jupytext's content manager: @@ -32,7 +32,7 @@ Pandoc's Markdown format is available in Jupytext as `md:pandoc`. This requires conda install pandoc -c conda-forge ``` -Pandoc's format uses Pandoc divs (`:::`) as explicit cell markers. See how our `World population.ipynb` notebook is [represented](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.pandoc.md#a-quick-insight-at-world-population) in that format. Please also note that `pandoc`, while preserving the HTML rendering, may reformat the text in some of the Markdown cells. If that is an issue for you, please wait until [jgm/pandoc#5408](https://github.com/jgm/pandoc/issues/5408) gets implemented. +Pandoc's format uses Pandoc divs (`:::`) as explicit cell markers. See how our `World population.ipynb` notebook is [represented](https://github.com/mwouts/jupytext/blob/master/demo/World%20population.pandoc.md#) in that format. Please also note that `pandoc`, while preserving the HTML rendering, may reformat the text in some of the Markdown cells. If that is an issue for you, please wait until [jgm/pandoc#5408](https://github.com/jgm/pandoc/issues/5408) gets implemented. Jupytext currently strips the output cells before calling `pandoc`. As for the other formats, outputs cells can be preserved in paired notebooks. In the case of the pandoc format, paired notebooks are available with the metadata `"jupytext": {"formats": "md:pandoc,ipynb"}`. diff --git a/docs/introduction.md b/docs/introduction.md index 09fe92d97..245630000 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -10,7 +10,7 @@ Jupytext can save Jupyter notebooks as - Markdown and R Markdown documents, - Scripts in many languages. -The languages that are currently supported by Jupytext are: Julia, Python, R, Bash, Scheme, Clojure, Matlab, Octave, C++, q/kdb+, IDL, TypeScript and Javascript. Extending Jupytext to more languages should be easy - read more at [CONTRIBUTING.md](https://github.com/mwouts/jupytext/blob/master/CONTRIBUTING.md). In addition, jupytext users can choose between two formats for notebooks as scripts: +The languages that are currently supported by Jupytext are: Julia, Python, R, Bash, Scheme, Clojure, Matlab, Octave, C++, q/kdb+, IDL, TypeScript and Javascript. Extending Jupytext to more languages should be easy - read more at [CONTRIBUTING.md](https://github.com/mwouts/jupytext/blob/master/CONTRIBUTING.md#). In addition, jupytext users can choose between two formats for notebooks as scripts: - The `percent` format, compatible with several IDEs, including Spyder, Hydrogen, VScode and PyCharm. In that format, cells are delimited with a commented `%%`. - The `light` format, designed for this project. Use that format to open standard scripts as notebooks, or to save notebooks as scripts with few cell markers - none when possible. @@ -42,7 +42,7 @@ In short: the Markdown representation of notebooks fits well the notebooks that Looking for a demo? - Read the original [announcement](https://towardsdatascience.com/introducing-jupytext-9234fdff6c57) in Towards Data Science, -- Watch the [PyParis talk](https://github.com/mwouts/jupytext_pyparis_2018/blob/master/README.md), +- Watch the [PyParis talk](https://github.com/mwouts/jupytext_pyparis_2018/blob/master/README.md#), - or, try Jupytext online with [binder](https://mybinder.org/v2/gh/mwouts/jupytext/master?urlpath=lab/tree/demo/get_started.ipynb)! ## Want to contribute? From f311812a31f3327ed9431fee7b4fd7f20cd97523 Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Thu, 20 Jun 2019 22:13:31 +0200 Subject: [PATCH 7/7] We don't have a "_static" folder --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index fcfdd2275..cd1eb1d18 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -56,7 +56,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] +html_static_path = [] # Output file base name for HTML help builder. htmlhelp_basename = "jupytext"