├── doc ├── build │ ├── latex │ │ ├── rpi.idx │ │ ├── rpi.ind │ │ ├── rpi.pdf │ │ ├── aapl.png │ │ ├── htop.png │ │ ├── stock_app_main.png │ │ ├── stock_app_plotly.png │ │ ├── stock_app_results.png │ │ ├── python.ist │ │ ├── rpi.ilg │ │ ├── rpi.out │ │ ├── rpi.toc │ │ ├── Makefile │ │ ├── sphinxhowto.cls │ │ ├── sphinxmanual.cls │ │ └── rpi.aux │ ├── html │ │ ├── favicon.ico │ │ ├── objects.inv │ │ ├── _images │ │ │ ├── aapl.png │ │ │ ├── htop.png │ │ │ ├── stock_app_main.png │ │ │ ├── stock_app_plotly.png │ │ │ └── stock_app_results.png │ │ ├── _static │ │ │ ├── down.png │ │ │ ├── file.png │ │ │ ├── plus.png │ │ │ ├── up.png │ │ │ ├── minus.png │ │ │ ├── comment.png │ │ │ ├── favicon.ico │ │ │ ├── favicon_.ico │ │ │ ├── ajax-loader.gif │ │ │ ├── up-pressed.png │ │ │ ├── comment-bright.png │ │ │ ├── comment-close.png │ │ │ ├── down-pressed.png │ │ │ ├── tpq_logo_white.png │ │ │ ├── tpq_logo_left_cut.png │ │ │ ├── tpq_logo_more_left_cut.png │ │ │ ├── pygments.css │ │ │ ├── sidebar.js │ │ │ ├── default.css │ │ │ └── doctools.js │ │ ├── _downloads │ │ │ ├── flask_test.py │ │ │ ├── results.html │ │ │ ├── web_serve.py │ │ │ ├── run_stock_app.py │ │ │ ├── run_stock_int.py │ │ │ ├── plotly.html │ │ │ ├── forms.py │ │ │ ├── layout.html │ │ │ ├── style.css │ │ │ ├── large_data_set.py │ │ │ ├── selection.html │ │ │ ├── data_collection.py │ │ │ ├── mail_simple.py │ │ │ ├── stock_data.py │ │ │ ├── mail_attach.py │ │ │ └── stock_interactive.py │ │ ├── .buildinfo │ │ ├── add_font.py │ │ ├── _sources │ │ │ ├── 01_ftp_server.txt │ │ │ ├── 04_git_server.txt │ │ │ ├── index.txt │ │ │ ├── 00_basic_config.txt │ │ │ ├── 02_data_analytics.txt │ │ │ ├── 05_webcam.txt │ │ │ └── 03_web_apps.txt │ │ ├── genindex.html │ │ ├── search.html │ │ ├── 01_ftp_server.html │ │ └── searchindex.js │ ├── doctrees │ │ ├── .doctree │ │ ├── ftp.doctree │ │ ├── ftp2.doctree │ │ ├── 00_ssh.doctree │ │ ├── 02_ftp.doctree │ │ ├── 03_ftp.doctree │ │ ├── index.doctree │ │ ├── 05_webcam.doctree │ │ ├── 01_ipython.doctree │ │ ├── 02_web_app.doctree │ │ ├── 03_web_apps.doctree │ │ ├── environment.pickle │ │ ├── 00_ssh_access.doctree │ │ ├── 01_ftp_server.doctree │ │ ├── 04_git_server.doctree │ │ ├── 00_basic_config.doctree │ │ └── 02_data_analytics.doctree │ └── replace.py ├── source │ ├── rpi.sublime-project │ ├── aapl.png │ ├── htop.png │ ├── _static │ │ ├── favicon.ico │ │ ├── tpq_logo_white.png │ │ ├── tpq_logo_left_cut.png │ │ └── tpq_logo_more_left_cut.png │ ├── stock_app_main.png │ ├── stock_app_plotly.png │ ├── stock_app_results.png │ ├── stock_app │ │ ├── static │ │ │ ├── results.png │ │ │ └── style.css │ │ ├── templates │ │ │ ├── results.html │ │ │ ├── layout.html │ │ │ └── selection.html │ │ ├── run_stock_app.py │ │ ├── forms.py │ │ └── stock_data.py │ ├── flask_test.py │ ├── web_serve.py │ ├── stock_int │ │ ├── run_stock_int.py │ │ ├── templates │ │ │ ├── plotly.html │ │ │ ├── layout.html │ │ │ └── selection.html │ │ ├── forms.py │ │ ├── static │ │ │ └── style.css │ │ └── stock_interactive.py │ ├── large_data_set.py │ ├── data_collection.py │ ├── mail_simple.py │ ├── 01_ftp_server.rst │ ├── mail_attach.py │ ├── 04_git_server.rst │ ├── index.rst │ ├── 00_basic_config.rst │ ├── 02_data_analytics.rst │ ├── 05_webcam.rst │ ├── 03_web_apps.rst │ └── conf.py ├── _store │ ├── mail.py │ └── mail_attach.py └── Makefile ├── rpi.png ├── .ipynb_checkpoints └── testing-checkpoint.ipynb ├── README.md ├── .gitignore └── LICENSE /doc/build/latex/rpi.idx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/build/latex/rpi.ind: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/source/rpi.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /rpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/rpi.png -------------------------------------------------------------------------------- /doc/source/aapl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/aapl.png -------------------------------------------------------------------------------- /doc/source/htop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/htop.png -------------------------------------------------------------------------------- /doc/build/latex/rpi.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/latex/rpi.pdf -------------------------------------------------------------------------------- /doc/build/html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/favicon.ico -------------------------------------------------------------------------------- /doc/build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/objects.inv -------------------------------------------------------------------------------- /doc/build/latex/aapl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/latex/aapl.png -------------------------------------------------------------------------------- /doc/build/latex/htop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/latex/htop.png -------------------------------------------------------------------------------- /doc/build/doctrees/.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/ftp.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/ftp.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/ftp2.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/ftp2.doctree -------------------------------------------------------------------------------- /doc/build/html/_images/aapl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_images/aapl.png -------------------------------------------------------------------------------- /doc/build/html/_images/htop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_images/htop.png -------------------------------------------------------------------------------- /doc/build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/down.png -------------------------------------------------------------------------------- /doc/build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/file.png -------------------------------------------------------------------------------- /doc/build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/plus.png -------------------------------------------------------------------------------- /doc/build/html/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/up.png -------------------------------------------------------------------------------- /doc/source/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/_static/favicon.ico -------------------------------------------------------------------------------- /doc/source/stock_app_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/stock_app_main.png -------------------------------------------------------------------------------- /doc/source/stock_app_plotly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/stock_app_plotly.png -------------------------------------------------------------------------------- /doc/build/doctrees/00_ssh.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/00_ssh.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/02_ftp.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/02_ftp.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/03_ftp.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/03_ftp.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/index.doctree -------------------------------------------------------------------------------- /doc/build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/minus.png -------------------------------------------------------------------------------- /doc/source/stock_app_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/stock_app_results.png -------------------------------------------------------------------------------- /doc/build/doctrees/05_webcam.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/05_webcam.doctree -------------------------------------------------------------------------------- /doc/build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/comment.png -------------------------------------------------------------------------------- /doc/build/html/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/favicon.ico -------------------------------------------------------------------------------- /doc/build/html/_static/favicon_.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/favicon_.ico -------------------------------------------------------------------------------- /doc/build/latex/stock_app_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/latex/stock_app_main.png -------------------------------------------------------------------------------- /doc/build/latex/stock_app_plotly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/latex/stock_app_plotly.png -------------------------------------------------------------------------------- /doc/build/doctrees/01_ipython.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/01_ipython.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/02_web_app.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/02_web_app.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/03_web_apps.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/03_web_apps.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/environment.pickle -------------------------------------------------------------------------------- /doc/build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /doc/build/html/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/up-pressed.png -------------------------------------------------------------------------------- /doc/build/latex/stock_app_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/latex/stock_app_results.png -------------------------------------------------------------------------------- /doc/source/_static/tpq_logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/_static/tpq_logo_white.png -------------------------------------------------------------------------------- /doc/build/doctrees/00_ssh_access.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/00_ssh_access.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/01_ftp_server.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/01_ftp_server.doctree -------------------------------------------------------------------------------- /doc/build/doctrees/04_git_server.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/04_git_server.doctree -------------------------------------------------------------------------------- /doc/build/html/_images/stock_app_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_images/stock_app_main.png -------------------------------------------------------------------------------- /doc/build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /doc/build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/comment-close.png -------------------------------------------------------------------------------- /doc/build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /doc/build/html/_static/tpq_logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/tpq_logo_white.png -------------------------------------------------------------------------------- /doc/source/_static/tpq_logo_left_cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/_static/tpq_logo_left_cut.png -------------------------------------------------------------------------------- /doc/source/stock_app/static/results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/stock_app/static/results.png -------------------------------------------------------------------------------- /doc/build/doctrees/00_basic_config.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/00_basic_config.doctree -------------------------------------------------------------------------------- /doc/build/html/_images/stock_app_plotly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_images/stock_app_plotly.png -------------------------------------------------------------------------------- /doc/build/doctrees/02_data_analytics.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/doctrees/02_data_analytics.doctree -------------------------------------------------------------------------------- /doc/build/html/_images/stock_app_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_images/stock_app_results.png -------------------------------------------------------------------------------- /doc/build/html/_static/tpq_logo_left_cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/tpq_logo_left_cut.png -------------------------------------------------------------------------------- /doc/source/_static/tpq_logo_more_left_cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/source/_static/tpq_logo_more_left_cut.png -------------------------------------------------------------------------------- /doc/build/html/_static/tpq_logo_more_left_cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yhilpisch/rpi/master/doc/build/html/_static/tpq_logo_more_left_cut.png -------------------------------------------------------------------------------- /doc/source/flask_test.py: -------------------------------------------------------------------------------- 1 | # 2 | # From http://flask.pocoo.org 3 | # 4 | from flask import Flask 5 | app = Flask(__name__) 6 | 7 | @app.route("/") 8 | def hello(): 9 | return "Hello World!" 10 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/flask_test.py: -------------------------------------------------------------------------------- 1 | # 2 | # From http://flask.pocoo.org 3 | # 4 | from flask import Flask 5 | app = Flask(__name__) 6 | 7 | @app.route("/") 8 | def hello(): 9 | return "Hello World!" 10 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/testing-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:9d8bdfea4595c163c5beb70b377dddfd74e1aa80692627a0c265e75845d6beed" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [] 9 | } -------------------------------------------------------------------------------- /doc/build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 32040a6f104c5b6125adeeb60ce4a91d 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /doc/build/latex/python.ist: -------------------------------------------------------------------------------- 1 | line_max 100 2 | headings_flag 1 3 | heading_prefix " \\bigletter " 4 | 5 | preamble "\\begin{theindex} 6 | \\def\\bigletter#1{{\\Large\\sffamily#1}\\nopagebreak\\vspace{1mm}} 7 | 8 | " 9 | 10 | symhead_positive "{Symbols}" 11 | numhead_positive "{Numbers}" 12 | -------------------------------------------------------------------------------- /doc/build/latex/rpi.ilg: -------------------------------------------------------------------------------- 1 | This is makeindex, version 2.15 [TeX Live 2012] (kpathsea + Thai support). 2 | Scanning style file ./python.ist......done (6 attributes redefined, 0 ignored). 3 | Scanning input file rpi.idx...done (0 entries accepted, 0 rejected). 4 | Nothing written in rpi.ind. 5 | Transcript written in rpi.ilg. 6 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/results.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% block body %} 5 | 6 | 7 |

Results for Symbol {{ symbol }}

8 | 9 | 10 | 11 |

12 | 13 | {{ table | safe }} 14 | 15 | 16 | {% endblock %} -------------------------------------------------------------------------------- /doc/source/stock_app/templates/results.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% block body %} 5 | 6 | 7 |

Results for Symbol {{ symbol }}

8 | 9 | 10 | 11 |

12 | 13 | {{ table | safe }} 14 | 15 | 16 | {% endblock %} -------------------------------------------------------------------------------- /doc/source/web_serve.py: -------------------------------------------------------------------------------- 1 | # 2 | # From http://flask.pocoo.org 3 | # 4 | from tornado.wsgi import WSGIContainer 5 | from tornado.httpserver import HTTPServer 6 | from tornado.ioloop import IOLoop 7 | from flask_test import app 8 | 9 | http_server = HTTPServer(WSGIContainer(app)) 10 | http_server.listen(5000) # serving on port 5000 11 | IOLoop.instance().start() -------------------------------------------------------------------------------- /doc/build/html/_downloads/web_serve.py: -------------------------------------------------------------------------------- 1 | # 2 | # From http://flask.pocoo.org 3 | # 4 | from tornado.wsgi import WSGIContainer 5 | from tornado.httpserver import HTTPServer 6 | from tornado.ioloop import IOLoop 7 | from flask_test import app 8 | 9 | http_server = HTTPServer(WSGIContainer(app)) 10 | http_server.listen(5000) # serving on port 5000 11 | IOLoop.instance().start() -------------------------------------------------------------------------------- /doc/source/stock_app/run_stock_app.py: -------------------------------------------------------------------------------- 1 | # 2 | # WSGI Wrapper for the 3 | # Historical Stock Data App 4 | # 5 | # run_stock_app.py 6 | # 7 | from tornado.wsgi import WSGIContainer 8 | from tornado.httpserver import HTTPServer 9 | from tornado.ioloop import IOLoop 10 | from stock_data import app 11 | 12 | http_server = HTTPServer(WSGIContainer(app)) 13 | http_server.listen(8888) # serving on port 8888 14 | IOLoop.instance().start() -------------------------------------------------------------------------------- /doc/build/html/_downloads/run_stock_app.py: -------------------------------------------------------------------------------- 1 | # 2 | # WSGI Wrapper for the 3 | # Historical Stock Data App 4 | # 5 | # run_stock_app.py 6 | # 7 | from tornado.wsgi import WSGIContainer 8 | from tornado.httpserver import HTTPServer 9 | from tornado.ioloop import IOLoop 10 | from stock_data import app 11 | 12 | http_server = HTTPServer(WSGIContainer(app)) 13 | http_server.listen(8888) # serving on port 8888 14 | IOLoop.instance().start() -------------------------------------------------------------------------------- /doc/source/stock_int/run_stock_int.py: -------------------------------------------------------------------------------- 1 | # 2 | # WSGI Wrapper for the 3 | # Historical Stock Data App (Interactive) 4 | # 5 | # run_stock_int.py 6 | # 7 | from tornado.wsgi import WSGIContainer 8 | from tornado.httpserver import HTTPServer 9 | from tornado.ioloop import IOLoop 10 | from stock_interactive import app 11 | 12 | http_server = HTTPServer(WSGIContainer(app)) 13 | http_server.listen(8888) # serving on port 8888 14 | IOLoop.instance().start() -------------------------------------------------------------------------------- /doc/build/html/_downloads/run_stock_int.py: -------------------------------------------------------------------------------- 1 | # 2 | # WSGI Wrapper for the 3 | # Historical Stock Data App (Interactive) 4 | # 5 | # run_stock_int.py 6 | # 7 | from tornado.wsgi import WSGIContainer 8 | from tornado.httpserver import HTTPServer 9 | from tornado.ioloop import IOLoop 10 | from stock_interactive import app 11 | 12 | http_server = HTTPServer(WSGIContainer(app)) 13 | http_server.listen(8888) # serving on port 8888 14 | IOLoop.instance().start() -------------------------------------------------------------------------------- /doc/build/html/_downloads/plotly.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% block body %} 5 | 6 | 7 |

Results for Symbol {{ symbol }}

8 | 9 | 16 | 17 |

18 | 19 | {{ table | safe }} 20 | 21 | 22 | {% endblock %} -------------------------------------------------------------------------------- /doc/source/stock_int/templates/plotly.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% block body %} 5 | 6 | 7 |

Results for Symbol {{ symbol }}

8 | 9 | 16 | 17 |

18 | 19 | {{ table | safe }} 20 | 21 | 22 | {% endblock %} -------------------------------------------------------------------------------- /doc/build/html/add_font.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | to_add = "Symbol (eg AAPL, MSFT)', 13 | validators=[DataRequired()]) 14 | trend1 = TextField('Trend 1 (eg 20, 42)', 15 | validators=[DataRequired()]) 16 | trend2 = TextField('Trend 2 (eg 100, 252)', 17 | validators=[DataRequired()]) 18 | submit = SubmitField() -------------------------------------------------------------------------------- /doc/source/stock_int/forms.py: -------------------------------------------------------------------------------- 1 | # 2 | # Data input form 3 | # forms.py 4 | # 5 | 6 | from wtforms import TextField 7 | from wtforms.fields import SubmitField 8 | from wtforms.validators import DataRequired 9 | from flask.ext.wtf import Form 10 | 11 | class SymbolSearch(Form): 12 | symbol = TextField('Symbol (eg AAPL, MSFT)', 13 | validators=[DataRequired()]) 14 | trend1 = TextField('Trend 1 (eg 20, 42)', 15 | validators=[DataRequired()]) 16 | trend2 = TextField('Trend 2 (eg 100, 252)', 17 | validators=[DataRequired()]) 18 | submit = SubmitField() -------------------------------------------------------------------------------- /doc/build/html/_downloads/forms.py: -------------------------------------------------------------------------------- 1 | # 2 | # Data input form 3 | # forms.py 4 | # 5 | 6 | from wtforms import TextField 7 | from wtforms.fields import SubmitField 8 | from wtforms.validators import DataRequired 9 | from flask.ext.wtf import Form 10 | 11 | class SymbolSearch(Form): 12 | symbol = TextField('Symbol (eg AAPL, MSFT)', 13 | validators=[DataRequired()]) 14 | trend1 = TextField('Trend 1 (eg 20, 42)', 15 | validators=[DataRequired()]) 16 | trend2 = TextField('Trend 2 (eg 100, 252)', 17 | validators=[DataRequired()]) 18 | submit = SubmitField() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raspberry Pi for Serious Things 2 | 3 | It is almost more than a year ago that I bought my first Raspberry Pi (cf. http://raspberrypi.org). Apart from being a "nice toy", the RPi can be used for some serious things. 4 | 5 | This "little year end pet project" of mine is a try to cover a set of topics that might be of interest to those who want to use the RPi for such things like: 6 | 7 | * SSH access to your RPi "server" 8 | * data analytics with Python 9 | * Web app deployment 10 | * RPi as FTP server or 11 | * Web cam surveillance 12 | 13 | The current version of the tutorial is found under http://hilpisch.com/rpi/index.html. 14 | 15 | ![alt text](rpi.png "RPi for Serious Things") 16 | 17 | Would love to hear your feedback under github@hilpisch.com. 18 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Historical Stock Prices 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 14 | 15 | 17 | 18 |
19 | 20 | 23 | 24 |
25 | back to search 26 |
27 | {% block body %} 28 | 29 | {% endblock %} 30 |
-------------------------------------------------------------------------------- /doc/source/stock_app/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Historical Stock Prices 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 14 | 15 | 17 | 18 |
19 | 20 | 23 | 24 |
25 | back to search 26 |
27 | {% block body %} 28 | 29 | {% endblock %} 30 |
-------------------------------------------------------------------------------- /doc/source/stock_int/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Historical Stock Prices 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 14 | 15 | 17 | 18 |
19 | 20 | 23 | 24 |
25 | back to search 26 |
27 | {% block body %} 28 | 29 | {% endblock %} 30 |
-------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | develop-eggs/ 12 | dist/ 13 | downloads/ 14 | eggs/ 15 | lib/ 16 | lib64/ 17 | parts/ 18 | sdist/ 19 | var/ 20 | *.egg-info/ 21 | .installed.cfg 22 | *.egg 23 | 24 | # PyInstaller 25 | # Usually these files are written by a python script from a template 26 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 27 | *.manifest 28 | *.spec 29 | 30 | # Installer logs 31 | pip-log.txt 32 | pip-delete-this-directory.txt 33 | 34 | # Unit test / coverage reports 35 | htmlcov/ 36 | .tox/ 37 | .coverage 38 | .cache 39 | nosetests.xml 40 | coverage.xml 41 | 42 | # Translations 43 | *.mo 44 | *.pot 45 | 46 | # Django stuff: 47 | *.log 48 | 49 | # Sphinx documentation 50 | docs/_build/ 51 | 52 | # PyBuilder 53 | target/ 54 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/style.css: -------------------------------------------------------------------------------- 1 | /* style.css */ 2 | body { font-family: 'PT Sans', sans-serif; background: #eee; } 3 | a, h1, h2 { color: #021A80; } 4 | h1, h2 { font-family: 'PT Sans', sans-serif; margin: 0; text-align: center;} 5 | h1 { font-size: 1.4em; border-bottom: 2px solid #eee; } 6 | h2 { font-size: 1.0em; } 7 | 8 | a:link { color: #B40404; text-decoration:none; } 9 | a:visited { color: #B40404; text-decoration:none; } 10 | 11 | .dataframe { margin-left: auto; margin-right: auto;} 12 | 13 | .page { font-family: 'PT Sans', sans-serif; margin: 2em auto; width: 66em; 14 | padding: 0.8em; background: white; color: #021A80} 15 | 16 | .metanav { text-align: right; font-size: 1em; padding: 0.3em; 17 | margin-bottom: 1em; background: #fafafa; } 18 | 19 | .logo img { width: 30%; display: block; margin-right: auto; 20 | margin-left: auto; } 21 | 22 | .errors { font-size: 0.8em; color: red;} 23 | 24 | .form {text-align: center;} -------------------------------------------------------------------------------- /doc/source/stock_app/static/style.css: -------------------------------------------------------------------------------- 1 | /* style.css */ 2 | body { font-family: 'PT Sans', sans-serif; background: #eee; } 3 | a, h1, h2 { color: #021A80; } 4 | h1, h2 { font-family: 'PT Sans', sans-serif; margin: 0; text-align: center;} 5 | h1 { font-size: 1.4em; border-bottom: 2px solid #eee; } 6 | h2 { font-size: 1.0em; } 7 | 8 | a:link { color: #B40404; text-decoration:none; } 9 | a:visited { color: #B40404; text-decoration:none; } 10 | 11 | .dataframe { margin-left: auto; margin-right: auto;} 12 | 13 | .page { font-family: 'PT Sans', sans-serif; margin: 2em auto; width: 66em; 14 | padding: 0.8em; background: white; color: #021A80} 15 | 16 | .metanav { text-align: right; font-size: 1em; padding: 0.3em; 17 | margin-bottom: 1em; background: #fafafa; } 18 | 19 | .logo img { width: 30%; display: block; margin-right: auto; 20 | margin-left: auto; } 21 | 22 | .errors { font-size: 0.8em; color: red;} 23 | 24 | .form {text-align: center;} -------------------------------------------------------------------------------- /doc/source/stock_int/static/style.css: -------------------------------------------------------------------------------- 1 | /* style.css */ 2 | body { font-family: 'PT Sans', sans-serif; background: #eee; } 3 | a, h1, h2 { color: #021A80; } 4 | h1, h2 { font-family: 'PT Sans', sans-serif; margin: 0; text-align: center;} 5 | h1 { font-size: 1.4em; border-bottom: 2px solid #eee; } 6 | h2 { font-size: 1.0em; } 7 | 8 | a:link { color: #B40404; text-decoration:none; } 9 | a:visited { color: #B40404; text-decoration:none; } 10 | 11 | .dataframe { margin-left: auto; margin-right: auto;} 12 | 13 | .page { font-family: 'PT Sans', sans-serif; margin: 2em auto; width: 66em; 14 | padding: 0.8em; background: white; color: #021A80} 15 | 16 | .metanav { text-align: right; font-size: 1em; padding: 0.3em; 17 | margin-bottom: 1em; background: #fafafa; } 18 | 19 | .logo img { width: 30%; display: block; margin-right: auto; 20 | margin-left: auto; } 21 | 22 | .errors { font-size: 0.8em; color: red;} 23 | 24 | .form {text-align: center;} -------------------------------------------------------------------------------- /doc/source/large_data_set.py: -------------------------------------------------------------------------------- 1 | # 2 | # Storing a Larger Data Set on Disk 3 | # with Python/pandas/PyTables 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | import os 9 | from time import time 10 | import numpy as np 11 | import pandas as pd 12 | 13 | filename = 'data.h5' 14 | 15 | # 16 | # Generating the sample data 17 | # 18 | t0 = time() 19 | 20 | data = np.random.standard_normal(10000000) # random data 21 | 22 | df = pd.DataFrame(data) # pandas DataFrame object 23 | 24 | # 25 | # Storing data in HDF5 database 26 | # 27 | t1 = time() 28 | 29 | h5 = pd.HDFStore(filename, 'w') # open database file 30 | h5['data'] = df # write DataFrame to disk 31 | h5.close() # close database file 32 | 33 | t2 = time() 34 | os.remove(filename) # delete file on disk 35 | # 36 | # Output 37 | # 38 | print "Size of data set in bytes %d" % data.nbytes 39 | print "Time needed to generate data in sec. %5.2f" % (t1 - t0) 40 | print "Time needed to store data in sec. %5.2f" % (t2 - t1) 41 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/large_data_set.py: -------------------------------------------------------------------------------- 1 | # 2 | # Storing a Larger Data Set on Disk 3 | # with Python/pandas/PyTables 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | import os 9 | from time import time 10 | import numpy as np 11 | import pandas as pd 12 | 13 | filename = 'data.h5' 14 | 15 | # 16 | # Generating the sample data 17 | # 18 | t0 = time() 19 | 20 | data = np.random.standard_normal(10000000) # random data 21 | 22 | df = pd.DataFrame(data) # pandas DataFrame object 23 | 24 | # 25 | # Storing data in HDF5 database 26 | # 27 | t1 = time() 28 | 29 | h5 = pd.HDFStore(filename, 'w') # open database file 30 | h5['data'] = df # write DataFrame to disk 31 | h5.close() # close database file 32 | 33 | t2 = time() 34 | os.remove(filename) # delete file on disk 35 | # 36 | # Output 37 | # 38 | print "Size of data set in bytes %d" % data.nbytes 39 | print "Time needed to generate data in sec. %5.2f" % (t1 - t0) 40 | print "Time needed to store data in sec. %5.2f" % (t2 - t1) 41 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/selection.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% macro render_field(field) %} 5 |
{{ field.label }} 6 |
{{ field(**kwargs)|safe }} 7 | {% if field.errors %} 8 | 13 | {% endif %} 14 |
15 | {% endmacro %} 16 | 17 | {% block body %} 18 | 19 |
20 |
22 |
23 |

Search for a Ticker Symbol


24 | 25 |
Data will be retrieved from Yahoo! Finance.
Make sure to use a valid ticker symbol.


26 | 27 |
{{ render_field( form.symbol ) }}

28 |
{{ render_field( form.trend1 ) }}

29 |
{{ render_field( form.trend2 ) }}

30 |
{{ render_field( form.submit ) }}

31 | 32 |
33 |
34 |
35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /doc/source/stock_app/templates/selection.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% macro render_field(field) %} 5 |
{{ field.label }} 6 |
{{ field(**kwargs)|safe }} 7 | {% if field.errors %} 8 | 13 | {% endif %} 14 |
15 | {% endmacro %} 16 | 17 | {% block body %} 18 | 19 |
20 |
22 |
23 |

Search for a Ticker Symbol


24 | 25 |
Data will be retrieved from Yahoo! Finance.
Make sure to use a valid ticker symbol.


26 | 27 |
{{ render_field( form.symbol ) }}

28 |
{{ render_field( form.trend1 ) }}

29 |
{{ render_field( form.trend2 ) }}

30 |
{{ render_field( form.submit ) }}

31 | 32 |
33 |
34 |
35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /doc/source/stock_int/templates/selection.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "layout.html" %} 3 | 4 | {% macro render_field(field) %} 5 |
{{ field.label }} 6 |
{{ field(**kwargs)|safe }} 7 | {% if field.errors %} 8 | 13 | {% endif %} 14 |
15 | {% endmacro %} 16 | 17 | {% block body %} 18 | 19 |
20 |
22 |
23 |

Search for a Ticker Symbol


24 | 25 |
Data will be retrieved from Yahoo! Finance.
Make sure to use a valid ticker symbol.


26 | 27 |
{{ render_field( form.symbol ) }}

28 |
{{ render_field( form.trend1 ) }}

29 |
{{ render_field( form.trend2 ) }}

30 |
{{ render_field( form.submit ) }}

31 | 32 |
33 |
34 |
35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /doc/source/data_collection.py: -------------------------------------------------------------------------------- 1 | # 2 | # Collecting and Storing Stock Price Data 3 | # with Python/pandas/PyTables 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | import os 9 | from time import time 10 | import pandas as pd 11 | import pandas.io.data as web 12 | 13 | symbols = ['AAPL', 'YHOO', 'MSFT'] 14 | 15 | filename = 'data.h5' 16 | 17 | # 18 | # Collecting the data 19 | # 20 | t0 = time() 21 | store = {} # dictionary to store DataFrame objects 22 | 23 | for sym in symbols: 24 | store[sym] = web.DataReader(sym, data_source='yahoo', start='2000/1/1') 25 | 26 | # 27 | # Storing data in HDF5 database 28 | # 29 | t1 = time() 30 | 31 | h5 = pd.HDFStore(filename, 'w') # open database file 32 | 33 | for sym in symbols: 34 | h5[sym] = store[sym] # write DataFrame to disk 35 | 36 | h5.close() # close database 37 | 38 | t2 = time() 39 | os.remove(filename) # delete file on disk 40 | # 41 | # Output 42 | # 43 | print "Time needed to collect data in sec. %5.2f" % (t1 - t0) 44 | print "Time needed to store data in sec. %5.2f" % (t2 - t1) -------------------------------------------------------------------------------- /doc/build/html/_downloads/data_collection.py: -------------------------------------------------------------------------------- 1 | # 2 | # Collecting and Storing Stock Price Data 3 | # with Python/pandas/PyTables 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | import os 9 | from time import time 10 | import pandas as pd 11 | import pandas.io.data as web 12 | 13 | symbols = ['AAPL', 'YHOO', 'MSFT'] 14 | 15 | filename = 'data.h5' 16 | 17 | # 18 | # Collecting the data 19 | # 20 | t0 = time() 21 | store = {} # dictionary to store DataFrame objects 22 | 23 | for sym in symbols: 24 | store[sym] = web.DataReader(sym, data_source='yahoo', start='2000/1/1') 25 | 26 | # 27 | # Storing data in HDF5 database 28 | # 29 | t1 = time() 30 | 31 | h5 = pd.HDFStore(filename, 'w') # open database file 32 | 33 | for sym in symbols: 34 | h5[sym] = store[sym] # write DataFrame to disk 35 | 36 | h5.close() # close database 37 | 38 | t2 = time() 39 | os.remove(filename) # delete file on disk 40 | # 41 | # Output 42 | # 43 | print "Time needed to collect data in sec. %5.2f" % (t1 - t0) 44 | print "Time needed to store data in sec. %5.2f" % (t2 - t1) -------------------------------------------------------------------------------- /doc/build/replace.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | rpl = { 4 | '65p6tn4p8i': 'token', 5 | 'hilpisch13': 'username', 6 | 'henrynikolaus06': 'password', 7 | 'rpi@hilpisch.com': 'rpi@mydomain.net', 8 | 'yves@hilpisch.com': 'me@mydomain.net', 9 | 'ftp://rpi:pythonquants@quant-platform.com': 'ftp://user:password@mydomain.net', 10 | 'smtp.hilpisch.com': 'smtp.mydomain.net' 11 | } 12 | 13 | path = './html/' 14 | files = os.listdir(path) 15 | 16 | for path, dirs, files in os.walk(path): 17 | for f in files: 18 | print path + '/' + f 19 | if f.endswith('.html') or f.endswith('.py') \ 20 | or f.endswith('.conf') or f.endswith('.txt'): 21 | r = open(path + '/' + f, 'r').readlines() 22 | e = [] 23 | for l in r: 24 | for k, v in rpl.items(): 25 | l = l.replace(k, v) 26 | e.append(l) 27 | # r = [[l.replace(k, v) for k, v in rpl.items()] for l in r] 28 | n = open(path + '/' + f, 'w') 29 | n.writelines(e) 30 | n.close() 31 | 32 | for f in files: 33 | if f.endswith('.html_old'): 34 | os.remove(f) -------------------------------------------------------------------------------- /doc/build/html/_downloads/mail_simple.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sending emails in combination 3 | # with Motion surveillance software 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | 9 | import smtplib 10 | from datetime import datetime 11 | from email.MIMEMultipart import MIMEMultipart 12 | from email.MIMEText import MIMEText 13 | 14 | 15 | fromaddr = 'rpi@mydomain.net' 16 | toaddrs = 'me@mydomain.net' # can be list of strings 17 | subject = 'Security Alert.' 18 | 19 | # 20 | # Email object 21 | # 22 | msg = MIMEMultipart() 23 | msg['From'] = fromaddr 24 | msg['To'] = toaddrs 25 | msg['Subject'] = subject 26 | 27 | # 28 | # Email body 29 | # 30 | body = 'A motion has been detected.\nTime: %s' % str(datetime.now()) 31 | msg.attach(MIMEText(body, 'plain')) 32 | 33 | # 34 | # Connecting to SMTP server and 35 | # sending the email 36 | # 37 | smtp = smtplib.SMTP() 38 | smtp.set_debuglevel(1) 39 | smtp.connect('smtp.mydomain.net', 587) 40 | smtp.login('username', 'password') 41 | text = msg.as_string() 42 | smtp.sendmail(fromaddr, toaddrs, text) 43 | smtp.quit() 44 | 45 | # 46 | # Output 47 | # 48 | print "Message length is " + repr(len(msg)) 49 | print text 50 | -------------------------------------------------------------------------------- /doc/source/mail_simple.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sending emails in combination 3 | # with Motion surveillance software 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | 9 | import smtplib 10 | from datetime import datetime 11 | from email.MIMEMultipart import MIMEMultipart 12 | from email.MIMEText import MIMEText 13 | 14 | 15 | fromaddr = 'rpi@hilpisch.com' 16 | toaddrs = 'yves@hilpisch.com' # can be list of strings 17 | subject = 'Security Alert.' 18 | 19 | # 20 | # Email object 21 | # 22 | msg = MIMEMultipart() 23 | msg['From'] = fromaddr 24 | msg['To'] = toaddrs 25 | msg['Subject'] = subject 26 | 27 | # 28 | # Email body 29 | # 30 | body = 'A motion has been detected.\nTime: %s' % str(datetime.now()) 31 | msg.attach(MIMEText(body, 'plain')) 32 | 33 | # 34 | # Connecting to SMTP server and 35 | # sending the email 36 | # 37 | smtp = smtplib.SMTP() 38 | smtp.set_debuglevel(1) 39 | smtp.connect('smtp.hilpisch.com', 587) 40 | smtp.login('hilpisch13', 'henrynikolaus06') 41 | text = msg.as_string() 42 | smtp.sendmail(fromaddr, toaddrs, text) 43 | smtp.quit() 44 | 45 | # 46 | # Output 47 | # 48 | print "Message length is " + repr(len(msg)) 49 | print text 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Yves Hilpisch 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /doc/source/01_ftp_server.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _ftp_server: 3 | 4 | Raspberry Pi as FTP Server 5 | ------------------------------- 6 | 7 | Setting up the RPi as an FTP server---over which you and you alone have full control---is quite a simple task. First, install the ``ProFTP`` software through:: 8 | 9 | sudo apt-get install proftpd 10 | 11 | Configure it to be "standalone". Second, **edit the config file** of the program as follows:: 12 | 13 | sudo nano /etc/proftpd/proftpd.conf 14 | 15 | Add the following **parameters**:: 16 | 17 | DefaultRoot ~ 18 | AuthOrder mod_auth_file.c mod_auth_unix.c 19 | AuthUserFile /etc/proftpd/ftpd.passwd 20 | AuthPAM off 21 | RequireValidShell off 22 | 23 | **Restart** the service by:: 24 | 25 | sudo /etc/init.d/proftpd restart 26 | 27 | Third, **generate a new user** as follows:: 28 | 29 | sudo adduser ftp --home /home/ftp --shell /bin/bash 30 | 31 | Change ``ftp`` and ``/home/ftp`` to a user name and directory of your liking. Choose a password for the new user. 32 | 33 | Using a **FTP client**, you can now connect to your RPi and, for example, store files on it. You can also ``ssh`` connect to the RPi using the new user credentials. 34 | 35 | Generally SD cards hosting the OS of the RPi and serving as file/data storage are of course not that large. But investing e.g. **50 EUR for a 500 GB external USB drive** and connecting such a drive to the RPi is a simple way of using the RPi as a serious ``ftp`` server. -------------------------------------------------------------------------------- /doc/build/html/_sources/01_ftp_server.txt: -------------------------------------------------------------------------------- 1 | 2 | .. _ftp_server: 3 | 4 | Raspberry Pi as FTP Server 5 | ------------------------------- 6 | 7 | Setting up the RPi as an FTP server---over which you and you alone have full control---is quite a simple task. First, install the ``ProFTP`` software through:: 8 | 9 | sudo apt-get install proftpd 10 | 11 | Configure it to be "standalone". Second, **edit the config file** of the program as follows:: 12 | 13 | sudo nano /etc/proftpd/proftpd.conf 14 | 15 | Add the following **parameters**:: 16 | 17 | DefaultRoot ~ 18 | AuthOrder mod_auth_file.c mod_auth_unix.c 19 | AuthUserFile /etc/proftpd/ftpd.passwd 20 | AuthPAM off 21 | RequireValidShell off 22 | 23 | **Restart** the service by:: 24 | 25 | sudo /etc/init.d/proftpd restart 26 | 27 | Third, **generate a new user** as follows:: 28 | 29 | sudo adduser ftp --home /home/ftp --shell /bin/bash 30 | 31 | Change ``ftp`` and ``/home/ftp`` to a user name and directory of your liking. Choose a password for the new user. 32 | 33 | Using a **FTP client**, you can now connect to your RPi and, for example, store files on it. You can also ``ssh`` connect to the RPi using the new user credentials. 34 | 35 | Generally SD cards hosting the OS of the RPi and serving as file/data storage are of course not that large. But investing e.g. **50 EUR for a 500 GB external USB drive** and connecting such a drive to the RPi is a simple way of using the RPi as a serious ``ftp`` server. -------------------------------------------------------------------------------- /doc/source/stock_app/stock_data.py: -------------------------------------------------------------------------------- 1 | # 2 | # Historical Stock Prices 3 | # with the RPi using Python & Flask 4 | # 5 | # stock_data.py 6 | # 7 | # (c) Dr. Yves J. Hilpisch 8 | # The Python Quants 9 | # 10 | 11 | import pandas as pd 12 | import pandas.io.data as web 13 | import matplotlib.pyplot as plt 14 | from flask import Flask, request, render_template, redirect, url_for 15 | from forms import SymbolSearch 16 | 17 | 18 | app = Flask(__name__) 19 | 20 | @app.route("/", methods=['GET', 'POST']) 21 | def main(): 22 | form = SymbolSearch(csrf_enabled=False) 23 | if request.method == 'POST' and form.validate(): 24 | return redirect(url_for('results', symbol=request.form['symbol'], 25 | trend1=request.form['trend1'], 26 | trend2=request.form['trend2'])) 27 | return render_template('selection.html', form=form) 28 | 29 | @app.route("/symbol/++") 30 | def results(symbol, trend1, trend2): 31 | data = web.DataReader(symbol, data_source='yahoo') 32 | data['Trend 1'] = pd.rolling_mean(data['Adj Close'], window=int(trend1)) 33 | data['Trend 2'] = pd.rolling_mean(data['Adj Close'], window=int(trend2)) 34 | data[['Adj Close', 'Trend 1', 'Trend 2']].plot() 35 | output = 'results.png' 36 | plt.savefig('static/' + output) 37 | table = data.tail().to_html() 38 | return render_template('results.html', symbol=symbol, 39 | output=output, table=table) 40 | 41 | 42 | if __name__ == '__main__': 43 | app.run(debug=True) -------------------------------------------------------------------------------- /doc/build/html/_downloads/stock_data.py: -------------------------------------------------------------------------------- 1 | # 2 | # Historical Stock Prices 3 | # with the RPi using Python & Flask 4 | # 5 | # stock_data.py 6 | # 7 | # (c) Dr. Yves J. Hilpisch 8 | # The Python Quants 9 | # 10 | 11 | import pandas as pd 12 | import pandas.io.data as web 13 | import matplotlib.pyplot as plt 14 | from flask import Flask, request, render_template, redirect, url_for 15 | from forms import SymbolSearch 16 | 17 | 18 | app = Flask(__name__) 19 | 20 | @app.route("/", methods=['GET', 'POST']) 21 | def main(): 22 | form = SymbolSearch(csrf_enabled=False) 23 | if request.method == 'POST' and form.validate(): 24 | return redirect(url_for('results', symbol=request.form['symbol'], 25 | trend1=request.form['trend1'], 26 | trend2=request.form['trend2'])) 27 | return render_template('selection.html', form=form) 28 | 29 | @app.route("/symbol/++") 30 | def results(symbol, trend1, trend2): 31 | data = web.DataReader(symbol, data_source='yahoo') 32 | data['Trend 1'] = pd.rolling_mean(data['Adj Close'], window=int(trend1)) 33 | data['Trend 2'] = pd.rolling_mean(data['Adj Close'], window=int(trend2)) 34 | data[['Adj Close', 'Trend 1', 'Trend 2']].plot() 35 | output = 'results.png' 36 | plt.savefig('static/' + output) 37 | table = data.tail().to_html() 38 | return render_template('results.html', symbol=symbol, 39 | output=output, table=table) 40 | 41 | 42 | if __name__ == '__main__': 43 | app.run(debug=True) -------------------------------------------------------------------------------- /doc/_store/mail.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sending emails in combination 3 | # with Motion surveillance software 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | 9 | import smtplib 10 | from datetime import datetime 11 | from email.MIMEMultipart import MIMEMultipart 12 | from email.MIMEText import MIMEText 13 | 14 | 15 | def prompt(prompt): 16 | return raw_input(prompt).strip() 17 | 18 | fromaddr = 'rpi@hilpisch.com' # prompt("From: ") 19 | toaddrs = 'yves@hilpisch.com' # prompt("To: ") 20 | subject = 'Security Alert.' # prompt("Subject: ") 21 | 22 | msg = MIMEMultipart() 23 | msg['From'] = fromaddr 24 | msg['To'] = toaddrs 25 | msg['Subject'] = subject 26 | 27 | 28 | # Add the From: and To: headers at the start! 29 | # msg = ("From: %s\r\nTo: %s\r\n\r\nSubject: %s\r\n" 30 | # % (fromaddr, ", ".join(toaddrs), subject)) 31 | 32 | # print "Enter message, end with ^D (Unix) or ^Z (Windows):" 33 | 34 | # body = '' 35 | #while 1: 36 | # try: 37 | # line = raw_input() 38 | # except EOFError: 39 | # break 40 | # if not line: 41 | # break 42 | # body = body + line 43 | 44 | body = 'A motion has been detected.\nTime: %s' % str(datetime.now()) 45 | msg.attach(MIMEText(body, 'plain')) 46 | 47 | print "Message length is " + repr(len(msg)) 48 | 49 | smtp = smtplib.SMTP() 50 | # smtp.starttls() 51 | smtp.set_debuglevel(1) 52 | smtp.connect('smtp.hilpisch.com', 587) 53 | smtp.login('hilpisch13', 'henrynikolaus06') 54 | text = msg.as_string() 55 | smtp.sendmail(fromaddr, toaddrs, text) 56 | smtp.quit() 57 | print text 58 | -------------------------------------------------------------------------------- /doc/_store/mail_attach.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sending emails in combination 3 | # with Motion surveillance software 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | 9 | import argparse 10 | import smtplib 11 | from datetime import datetime 12 | from email.MIMEMultipart import MIMEMultipart 13 | from email.MIMEText import MIMEText 14 | from email.MIMEBase import MIMEBase 15 | from email import Encoders 16 | 17 | def prompt(prompt): 18 | return raw_input(prompt).strip() 19 | 20 | fromaddr = 'rpi@hilpisch.com' # prompt("From: ") 21 | toaddrs = 'yves@hilpisch.com' # prompt("To: ") 22 | subject = 'Video Evidence.' # prompt("Subject: ") 23 | 24 | msg = MIMEMultipart() 25 | msg['From'] = fromaddr 26 | msg['To'] = toaddrs 27 | msg['Subject'] = subject 28 | 29 | 30 | parser = argparse.ArgumentParser() 31 | parser.add_argument('input_file', help='Input file') 32 | args = parser.parse_args() 33 | 34 | 35 | part = MIMEBase('application', "octet-stream") 36 | part.set_payload(open(args.input_file, "rb").read()) 37 | Encoders.encode_base64(part) 38 | 39 | part.add_header('Content-Disposition', 'attachment; filename="%s"' % args.input_file) 40 | 41 | msg.attach(part) 42 | 43 | body = 'This video has been recorded due to a motion in your home office.\nTime: %s' % str(datetime.now()) 44 | msg.attach(MIMEText(body, 'plain')) 45 | 46 | print "Message length is " + repr(len(msg)) 47 | 48 | smtp = smtplib.SMTP() 49 | smtp.set_debuglevel(1) 50 | smtp.connect('smtp.hilpisch.com', 587) 51 | smtp.login('hilpisch12', 'henrynikolaus06') 52 | text = msg.as_string() 53 | smtp.sendmail(fromaddr, toaddrs, text) 54 | smtp.quit() 55 | print text 56 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/mail_attach.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sending emails in combination 3 | # with Motion surveillance software 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | 9 | import argparse 10 | import smtplib 11 | from datetime import datetime 12 | from email.MIMEMultipart import MIMEMultipart 13 | from email.MIMEText import MIMEText 14 | from email.MIMEBase import MIMEBase 15 | from email import Encoders 16 | 17 | fromaddr = 'rpi@mydomain.net' 18 | toaddrs = 'me@mydomain.net' # can be list of strings 19 | subject = 'Video Recorded.' 20 | 21 | # 22 | # Email object 23 | # 24 | msg = MIMEMultipart() 25 | msg['From'] = fromaddr 26 | msg['To'] = toaddrs 27 | msg['Subject'] = subject 28 | 29 | 30 | # 31 | # Email attachement 32 | # 33 | parser = argparse.ArgumentParser() 34 | parser.add_argument('input_file', help='Input file') 35 | args = parser.parse_args() 36 | 37 | part = MIMEBase('application', "octet-stream") 38 | part.set_payload(open(args.input_file, "rb").read()) 39 | Encoders.encode_base64(part) 40 | 41 | part.add_header('Content-Disposition', 42 | 'attachment; filename="%s"' % args.input_file) 43 | 44 | msg.attach(part) 45 | 46 | # 47 | # Email body 48 | # 49 | body = 'This video has been recorded due to a motion just detected.' 50 | body += '\nTime: %s' % str(datetime.now()) 51 | msg.attach(MIMEText(body, 'plain')) 52 | 53 | # 54 | # Connecting to SMTP server and 55 | # sending the email 56 | # 57 | smtp = smtplib.SMTP() 58 | smtp.set_debuglevel(1) 59 | smtp.connect('smtp.mydomain.net', 587) 60 | smtp.login('username', 'password') 61 | text = msg.as_string() 62 | smtp.sendmail(fromaddr, toaddrs, text) 63 | smtp.quit() 64 | 65 | # Shell output 66 | print "Message length is " + repr(len(msg)) 67 | print text 68 | -------------------------------------------------------------------------------- /doc/source/mail_attach.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sending emails in combination 3 | # with Motion surveillance software 4 | # 5 | # (c) Dr. Yves J. Hilpisch 6 | # The Python Quants GmbH 7 | # 8 | 9 | import argparse 10 | import smtplib 11 | from datetime import datetime 12 | from email.MIMEMultipart import MIMEMultipart 13 | from email.MIMEText import MIMEText 14 | from email.MIMEBase import MIMEBase 15 | from email import Encoders 16 | 17 | fromaddr = 'rpi@hilpisch.com' 18 | toaddrs = 'yves@hilpisch.com' # can be list of strings 19 | subject = 'Video Recorded.' 20 | 21 | # 22 | # Email object 23 | # 24 | msg = MIMEMultipart() 25 | msg['From'] = fromaddr 26 | msg['To'] = toaddrs 27 | msg['Subject'] = subject 28 | 29 | 30 | # 31 | # Email attachement 32 | # 33 | parser = argparse.ArgumentParser() 34 | parser.add_argument('input_file', help='Input file') 35 | args = parser.parse_args() 36 | 37 | part = MIMEBase('application', "octet-stream") 38 | part.set_payload(open(args.input_file, "rb").read()) 39 | Encoders.encode_base64(part) 40 | 41 | part.add_header('Content-Disposition', 42 | 'attachment; filename="%s"' % args.input_file) 43 | 44 | msg.attach(part) 45 | 46 | # 47 | # Email body 48 | # 49 | body = 'This video has been recorded due to a motion just detected.' 50 | body += '\nTime: %s' % str(datetime.now()) 51 | msg.attach(MIMEText(body, 'plain')) 52 | 53 | # 54 | # Connecting to SMTP server and 55 | # sending the email 56 | # 57 | smtp = smtplib.SMTP() 58 | smtp.set_debuglevel(1) 59 | smtp.connect('smtp.hilpisch.com', 587) 60 | smtp.login('hilpisch13', 'henrynikolaus06') 61 | text = msg.as_string() 62 | smtp.sendmail(fromaddr, toaddrs, text) 63 | smtp.quit() 64 | 65 | # Shell output 66 | print "Message length is " + repr(len(msg)) 67 | print text 68 | -------------------------------------------------------------------------------- /doc/build/latex/rpi.toc: -------------------------------------------------------------------------------- 1 | \select@language {english} 2 | \contentsline {chapter}{\numberline {1}Setting up the RPi}{3}{chapter.1} 3 | \contentsline {chapter}{\numberline {2}Booting the RPi}{5}{chapter.2} 4 | \contentsline {chapter}{\numberline {3}Small Projects with the RPi}{7}{chapter.3} 5 | \contentsline {section}{\numberline {3.1}Basic Configurations}{7}{section.3.1} 6 | \contentsline {subsection}{\numberline {3.1.1}SSH Access}{7}{subsection.3.1.1} 7 | \contentsline {subsubsection}{Fixed IP Address}{7}{subsubsection*.3} 8 | \contentsline {subsubsection}{Public IP Address}{8}{subsubsection*.4} 9 | \contentsline {subsubsection}{Using Public Keys}{8}{subsubsection*.5} 10 | \contentsline {subsection}{\numberline {3.1.2}Other Useful Tools \& Configurations}{8}{subsection.3.1.2} 11 | \contentsline {subsubsection}{Session Management with Screen}{8}{subsubsection*.6} 12 | \contentsline {subsubsection}{System Monitoring with htop}{9}{subsubsection*.7} 13 | \contentsline {subsubsection}{Enlarging the Swap Capacity}{9}{subsubsection*.8} 14 | \contentsline {section}{\numberline {3.2}Raspberry Pi as FTP Server}{10}{section.3.2} 15 | \contentsline {section}{\numberline {3.3}Raspberry Pi for Data Analytics}{10}{section.3.3} 16 | \contentsline {subsection}{\numberline {3.3.1}Installing Data Analytics Libraries}{11}{subsection.3.3.1} 17 | \contentsline {subsection}{\numberline {3.3.2}Interactive Data Analytics}{11}{subsection.3.3.2} 18 | \contentsline {subsection}{\numberline {3.3.3}Fast I/O Operations}{13}{subsection.3.3.3} 19 | \contentsline {section}{\numberline {3.4}Web Apps with Raspberry Pi}{15}{section.3.4} 20 | \contentsline {subsection}{\numberline {3.4.1}A First Example}{15}{subsection.3.4.1} 21 | \contentsline {subsection}{\numberline {3.4.2}Historical Stock Price Data}{16}{subsection.3.4.2} 22 | \contentsline {subsection}{\numberline {3.4.3}Generating Interactive D3 Plots}{21}{subsection.3.4.3} 23 | \contentsline {chapter}{\numberline {4}About the Author}{25}{chapter.4} 24 | \contentsline {chapter}{\numberline {5}Copyright \& Disclaimer}{27}{chapter.5} 25 | -------------------------------------------------------------------------------- /doc/build/latex/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx LaTeX output 2 | 3 | ALLDOCS = $(basename $(wildcard *.tex)) 4 | ALLPDF = $(addsuffix .pdf,$(ALLDOCS)) 5 | ALLDVI = $(addsuffix .dvi,$(ALLDOCS)) 6 | 7 | # Prefix for archive names 8 | ARCHIVEPRREFIX = 9 | # Additional LaTeX options 10 | LATEXOPTS = 11 | 12 | all: $(ALLPDF) 13 | all-pdf: $(ALLPDF) 14 | all-dvi: $(ALLDVI) 15 | all-ps: all-dvi 16 | for f in *.dvi; do dvips $$f; done 17 | 18 | all-pdf-ja: 19 | for f in *.pdf *.png *.gif *.jpg *.jpeg; do extractbb $$f; done 20 | for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done 21 | for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done 22 | for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done 23 | -for f in *.idx; do mendex -U -f -d "`basename $$f .idx`.dic" -s python.ist $$f; done 24 | for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done 25 | for f in *.tex; do platex -kanji=utf8 $(LATEXOPTS) $$f; done 26 | for f in *.dvi; do dvipdfmx $$f; done 27 | 28 | zip: all-$(FMT) 29 | mkdir $(ARCHIVEPREFIX)docs-$(FMT) 30 | cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) 31 | zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT) 32 | rm -r $(ARCHIVEPREFIX)docs-$(FMT) 33 | 34 | tar: all-$(FMT) 35 | mkdir $(ARCHIVEPREFIX)docs-$(FMT) 36 | cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) 37 | tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT) 38 | rm -r $(ARCHIVEPREFIX)docs-$(FMT) 39 | 40 | bz2: tar 41 | bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar 42 | 43 | # The number of LaTeX runs is quite conservative, but I don't expect it 44 | # to get run often, so the little extra time won't hurt. 45 | %.dvi: %.tex 46 | latex $(LATEXOPTS) '$<' 47 | latex $(LATEXOPTS) '$<' 48 | latex $(LATEXOPTS) '$<' 49 | -makeindex -s python.ist '$(basename $<).idx' 50 | latex $(LATEXOPTS) '$<' 51 | latex $(LATEXOPTS) '$<' 52 | 53 | %.pdf: %.tex 54 | pdflatex $(LATEXOPTS) '$<' 55 | pdflatex $(LATEXOPTS) '$<' 56 | pdflatex $(LATEXOPTS) '$<' 57 | -makeindex -s python.ist '$(basename $<).idx' 58 | pdflatex $(LATEXOPTS) '$<' 59 | pdflatex $(LATEXOPTS) '$<' 60 | 61 | clean: 62 | rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla 63 | 64 | .PHONY: all all-pdf all-dvi all-ps clean 65 | .PHONY: all-pdf-ja 66 | 67 | -------------------------------------------------------------------------------- /doc/build/html/_downloads/stock_interactive.py: -------------------------------------------------------------------------------- 1 | # 2 | # Historical Stock Prices 3 | # with the RPi using Python & Flask & Plotly 4 | # 5 | # stock_interactive.py 6 | # 7 | # (c) Dr. Yves J. Hilpisch 8 | # The Python Quants 9 | # 10 | 11 | import pandas as pd 12 | import pandas.io.data as web 13 | import matplotlib.pyplot as plt 14 | import plotly.plotly as ply 15 | from plotly.graph_objs import Figure, Layout, XAxis, YAxis 16 | from flask import Flask, request, render_template, redirect, url_for 17 | from forms import SymbolSearch 18 | 19 | # 20 | # Needed for plotly usage 21 | # 22 | 23 | ply.sign_in('yves', 'token') 24 | 25 | def df_to_plotly(df): 26 | ''' 27 | Converting a pandas DataFrame to plotly compatible format. 28 | ''' 29 | if df.index.__class__.__name__=="DatetimeIndex": 30 | x = df.index.format() 31 | else: 32 | x = df.index.values 33 | lines = {} 34 | for key in df: 35 | lines[key] = {} 36 | lines[key]['x'] = x 37 | lines[key]['y'] = df[key].values 38 | lines[key]['name'] = key 39 | lines_plotly = [lines[key] for key in df] 40 | return lines_plotly 41 | 42 | # 43 | # Main app 44 | # 45 | 46 | app = Flask(__name__) 47 | 48 | @app.route("/", methods=['GET', 'POST']) 49 | def main(): 50 | form = SymbolSearch(csrf_enabled=False) 51 | if request.method == 'POST' and form.validate(): 52 | return redirect(url_for('results', symbol=request.form['symbol'], 53 | trend1=request.form['trend1'], 54 | trend2=request.form['trend2'])) 55 | return render_template('selection.html', form=form) 56 | 57 | @app.route("/symbol/++") 58 | def results(symbol, trend1, trend2): 59 | data = web.DataReader(symbol, data_source='yahoo') 60 | data['Trend 1'] = pd.rolling_mean(data['Adj Close'], window=int(trend1)) 61 | data['Trend 2'] = pd.rolling_mean(data['Adj Close'], window=int(trend2)) 62 | layout = Layout( 63 | xaxis=XAxis(showgrid=True, gridcolor='#bdbdbd', gridwidth=2), 64 | yaxis=YAxis(showgrid=True, gridcolor='#bdbdbd', gridwidth=2) 65 | ) 66 | fig = Figure(data=df_to_plotly(data[['Adj Close', 'Trend 1', 'Trend 2']]), 67 | layout=layout) 68 | plot = ply.plot(fig, auto_open=False) 69 | table = data.tail().to_html() 70 | return render_template('plotly.html', symbol=symbol, 71 | plot=plot, table=table) 72 | 73 | 74 | if __name__ == '__main__': 75 | app.run(debug=True) -------------------------------------------------------------------------------- /doc/source/stock_int/stock_interactive.py: -------------------------------------------------------------------------------- 1 | # 2 | # Historical Stock Prices 3 | # with the RPi using Python & Flask & Plotly 4 | # 5 | # stock_interactive.py 6 | # 7 | # (c) Dr. Yves J. Hilpisch 8 | # The Python Quants 9 | # 10 | 11 | import pandas as pd 12 | import pandas.io.data as web 13 | import matplotlib.pyplot as plt 14 | import plotly.plotly as ply 15 | from plotly.graph_objs import Figure, Layout, XAxis, YAxis 16 | from flask import Flask, request, render_template, redirect, url_for 17 | from forms import SymbolSearch 18 | 19 | # 20 | # Needed for plotly usage 21 | # 22 | 23 | ply.sign_in('yves', '65p6tn4p8i') 24 | 25 | def df_to_plotly(df): 26 | ''' 27 | Converting a pandas DataFrame to plotly compatible format. 28 | ''' 29 | if df.index.__class__.__name__=="DatetimeIndex": 30 | x = df.index.format() 31 | else: 32 | x = df.index.values 33 | lines = {} 34 | for key in df: 35 | lines[key] = {} 36 | lines[key]['x'] = x 37 | lines[key]['y'] = df[key].values 38 | lines[key]['name'] = key 39 | lines_plotly = [lines[key] for key in df] 40 | return lines_plotly 41 | 42 | # 43 | # Main app 44 | # 45 | 46 | app = Flask(__name__) 47 | 48 | @app.route("/", methods=['GET', 'POST']) 49 | def main(): 50 | form = SymbolSearch(csrf_enabled=False) 51 | if request.method == 'POST' and form.validate(): 52 | return redirect(url_for('results', symbol=request.form['symbol'], 53 | trend1=request.form['trend1'], 54 | trend2=request.form['trend2'])) 55 | return render_template('selection.html', form=form) 56 | 57 | @app.route("/symbol/++") 58 | def results(symbol, trend1, trend2): 59 | data = web.DataReader(symbol, data_source='yahoo') 60 | data['Trend 1'] = pd.rolling_mean(data['Adj Close'], window=int(trend1)) 61 | data['Trend 2'] = pd.rolling_mean(data['Adj Close'], window=int(trend2)) 62 | layout = Layout( 63 | xaxis=XAxis(showgrid=True, gridcolor='#bdbdbd', gridwidth=2), 64 | yaxis=YAxis(showgrid=True, gridcolor='#bdbdbd', gridwidth=2) 65 | ) 66 | fig = Figure(data=df_to_plotly(data[['Adj Close', 'Trend 1', 'Trend 2']]), 67 | layout=layout) 68 | plot = ply.plot(fig, auto_open=False) 69 | table = data.tail().to_html() 70 | return render_template('plotly.html', symbol=symbol, 71 | plot=plot, table=table) 72 | 73 | 74 | if __name__ == '__main__': 75 | app.run(debug=True) -------------------------------------------------------------------------------- /doc/build/latex/sphinxhowto.cls: -------------------------------------------------------------------------------- 1 | % 2 | % sphinxhowto.cls for Sphinx (http://sphinx-doc.org/) 3 | % 4 | 5 | \NeedsTeXFormat{LaTeX2e}[1995/12/01] 6 | \ProvidesClass{sphinxhowto}[2009/06/02 Document class (Sphinx HOWTO)] 7 | 8 | % 'oneside' option overriding the 'twoside' default 9 | \newif\if@oneside 10 | \DeclareOption{oneside}{\@onesidetrue} 11 | % Pass remaining document options to the parent class. 12 | \DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}} 13 | \ProcessOptions\relax 14 | 15 | % Default to two-side document 16 | \if@oneside 17 | % nothing to do (oneside is the default) 18 | \else 19 | \PassOptionsToClass{twoside}{\sphinxdocclass} 20 | \fi 21 | 22 | \LoadClass{\sphinxdocclass} 23 | 24 | % Set some sane defaults for section numbering depth and TOC depth. You can 25 | % reset these counters in your preamble. 26 | % 27 | \setcounter{secnumdepth}{2} 28 | 29 | % Change the title page to look a bit better, and fit in with the fncychap 30 | % ``Bjarne'' style a bit better. 31 | % 32 | \renewcommand{\maketitle}{ 33 | \rule{\textwidth}{1pt} 34 | \ifsphinxpdfoutput 35 | \begingroup 36 | % These \defs are required to deal with multi-line authors; it 37 | % changes \\ to ', ' (comma-space), making it pass muster for 38 | % generating document info in the PDF file. 39 | \def\\{, } 40 | \def\and{and } 41 | \pdfinfo{ 42 | /Author (\@author) 43 | /Title (\@title) 44 | } 45 | \endgroup 46 | \fi 47 | \begin{flushright} 48 | \sphinxlogo% 49 | {\rm\Huge\py@HeaderFamily \@title} \par 50 | {\em\large\py@HeaderFamily \py@release\releaseinfo} \par 51 | \vspace{25pt} 52 | {\Large\py@HeaderFamily 53 | \begin{tabular}[t]{c} 54 | \@author 55 | \end{tabular}} \par 56 | \vspace{25pt} 57 | \@date \par 58 | \py@authoraddress \par 59 | \end{flushright} 60 | \@thanks 61 | \setcounter{footnote}{0} 62 | \let\thanks\relax\let\maketitle\relax 63 | %\gdef\@thanks{}\gdef\@author{}\gdef\@title{} 64 | } 65 | 66 | \let\py@OldTableofcontents=\tableofcontents 67 | \renewcommand{\tableofcontents}{ 68 | \begingroup 69 | \parskip = 0mm 70 | \py@OldTableofcontents 71 | \endgroup 72 | \rule{\textwidth}{1pt} 73 | \vspace{12pt} 74 | } 75 | 76 | \@ifundefined{fancyhf}{ 77 | \pagestyle{plain}}{ 78 | \pagestyle{normal}} % start this way; change for 79 | \pagenumbering{arabic} % ToC & chapters 80 | 81 | \thispagestyle{empty} 82 | 83 | % Fix the bibliography environment to add an entry to the Table of 84 | % Contents. 85 | % For an article document class this environment is a section, 86 | % so no page break before it. 87 | \let\py@OldThebibliography=\thebibliography 88 | \renewcommand{\thebibliography}[1]{ 89 | \phantomsection 90 | \py@OldThebibliography{1} 91 | \addcontentsline{toc}{section}{\bibname} 92 | } 93 | 94 | % Same for the indices. 95 | % The memoir class already does this, so we don't duplicate it in that case. 96 | % 97 | \@ifclassloaded{memoir}{}{ 98 | \let\py@OldTheindex=\theindex 99 | \renewcommand{\theindex}{ 100 | \phantomsection 101 | \py@OldTheindex 102 | \addcontentsline{toc}{section}{\indexname} 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /doc/build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index — Raspberry Pi for Serious Things 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 40 | 41 |
42 |
43 |
44 |
45 | 46 | 47 |

Index

48 | 49 |
50 | 51 |
52 | 53 | 54 |
55 |
56 |
57 |
58 |
59 | 62 | 63 | 64 | 65 | 77 | 78 |
79 |
80 |
81 |
82 | 91 | 95 | 96 | -------------------------------------------------------------------------------- /doc/build/html/search.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Search — Raspberry Pi for Serious Things 10 | 11 | 12 | 13 | 14 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 47 | 48 |
49 |
50 |
51 |
52 | 53 |

Search

54 |
55 | 56 |

57 | Please activate JavaScript to enable the search 58 | functionality. 59 |

60 |
61 |

62 | From here you can search these documents. Enter your search 63 | words into the box below and click "search". Note that the search 64 | function will automatically search for all of the words. Pages 65 | containing fewer words won't appear in the result list. 66 |

67 |
68 | 69 | 70 | 71 |
72 | 73 |
74 | 75 |
76 | 77 |
78 |
79 |
80 |
81 |
82 | 85 |
86 |
87 |
88 |
89 | 98 | 102 | 103 | -------------------------------------------------------------------------------- /doc/source/04_git_server.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _git_server: 3 | 4 | Git Server with Raspberry Pi 5 | ------------------------------- 6 | 7 | The version control system **Git** (cf. the excellent documentation under http://git-scm.com/) has become really popular recently. One reason for this is the success of **Github** (cf. http:github.com) as a (open source) code hosting platform based on Git. There are now also similar, alternative platforms available, like **Codebreak** (http://codebreak.com). 8 | 9 | While, for example, Codebreak let's you store as many private Git repositories as you like, with Github you have to pay for this feature. However, in principle, every server can serve as a Git server (even if not with the many nice, graphical features the aforementioned platforms provide). 10 | 11 | To use the RPi as a **Git server** (or a "remote Git repository storage system") does not require software-wise anything more the **Git installed** on the RPi. It should be installed already, if not do:: 12 | 13 | sudo apt-get install git 14 | 15 | In addition, the RPi must be configured for **SSH access** (cf. :ref:`ssh_access`). 16 | 17 | Using a USB Storage Device 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | 20 | In what follows, we use a **USB storage device** to store the remote Git repositories. This allows to move your valuable backups/versions of your Git repositories and to access them from other devices as well. 21 | 22 | Put a formatted USB stick into your RPi. The look up the **mounting information**:: 23 | 24 | sudo blkid 25 | 26 | In my case, it is mounted as ``/dev/sda1``. We want to **permanently link** the USB storage device to a directory in our home folder:: 27 | 28 | mkdir /home/pi/usb 29 | 30 | **Edit** the following file:: 31 | 32 | sudo nano /etc/fstab 33 | 34 | and **add** the line:: 35 | 36 | /dev/sda1 /home/pi/usb ext4 uid=pi, gid=pi, umask=0022, sync, auto, nosuid, rw, nouser 0 0 37 | 38 | where some parameters might need to be changed due to your configuration (e.g. the directory or ``vfat`` instead of ``ext4`` for the file system). 39 | 40 | After a **reboot**, you should now be able to permanently access the ("any") USB drive plugged into your RPi via ``/home/pi/usb``. 41 | 42 | 43 | Remote Repository on the RPi 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | Now that we have a proper storage device configured, we can **add a remote repository** to an existing one (I assume you are working with Git already and have a few repositories to use now; if not see below). 47 | 48 | In my case, I take the repository of this tutorial which you can also find under http://github.com/yhilpisch/rpi as an example. Now do **on the RPi** the following:: 49 | 50 | cd /home/pi/usb 51 | mkdir rpi.git 52 | cd rpi.git 53 | git init --bare 54 | 55 | Then navigate on your **local machine** to the Git repository you want to push to the remote RPi location and do (cf. also :ref:`fixip` for the domain name):: 56 | 57 | git remote add rpi pi@rpi.mydomain.net:/home/pi/usb/rpi.git 58 | 59 | Then, you should be able to do something like:: 60 | 61 | git push rpi master 62 | 63 | You can then, for instance, **clone the repository** to some other location via:: 64 | 65 | git clone pi@rpi.mydomain.net:/home/pi/usb/rpi.git 66 | 67 | Of course, you can also generate a **new user**, say ``git``, whose credentials you can easily and safely share with members of your team or with friends. You only have to make sure that this new user has read (or even maybe write) rights to the respective Git repository/folder (e.g. ``sudo chmod -R 755 /home/pi/usb/rpi``). 68 | 69 | 70 | Generating Local Git Repository 71 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 72 | 73 | If you **do not have** an example **Git repository** (but Git installed locally), you can do the following steps **locally** (assuming the the remote location was set up as above):: 74 | 75 | mkdir rpi 76 | cd rpi 77 | git init 78 | # copy now some files into the the new directory 79 | git add --all . 80 | git commit -am 'Initial commit message.' 81 | git remote add rpi pi@rpi.mydomain.net:/home/pi/usb/rpi.git 82 | git push rpi master 83 | -------------------------------------------------------------------------------- /doc/build/html/_sources/04_git_server.txt: -------------------------------------------------------------------------------- 1 | 2 | .. _git_server: 3 | 4 | Git Server with Raspberry Pi 5 | ------------------------------- 6 | 7 | The version control system **Git** (cf. the excellent documentation under http://git-scm.com/) has become really popular recently. One reason for this is the success of **Github** (cf. http:github.com) as a (open source) code hosting platform based on Git. There are now also similar, alternative platforms available, like **Codebreak** (http://codebreak.com). 8 | 9 | While, for example, Codebreak let's you store as many private Git repositories as you like, with Github you have to pay for this feature. However, in principle, every server can serve as a Git server (even if not with the many nice, graphical features the aforementioned platforms provide). 10 | 11 | To use the RPi as a **Git server** (or a "remote Git repository storage system") does not require software-wise anything more the **Git installed** on the RPi. It should be installed already, if not do:: 12 | 13 | sudo apt-get install git 14 | 15 | In addition, the RPi must be configured for **SSH access** (cf. :ref:`ssh_access`). 16 | 17 | Using a USB Storage Device 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | 20 | In what follows, we use a **USB storage device** to store the remote Git repositories. This allows to move your valuable backups/versions of your Git repositories and to access them from other devices as well. 21 | 22 | Put a formatted USB stick into your RPi. The look up the **mounting information**:: 23 | 24 | sudo blkid 25 | 26 | In my case, it is mounted as ``/dev/sda1``. We want to **permanently link** the USB storage device to a directory in our home folder:: 27 | 28 | mkdir /home/pi/usb 29 | 30 | **Edit** the following file:: 31 | 32 | sudo nano /etc/fstab 33 | 34 | and **add** the line:: 35 | 36 | /dev/sda1 /home/pi/usb ext4 uid=pi, gid=pi, umask=0022, sync, auto, nosuid, rw, nouser 0 0 37 | 38 | where some parameters might need to be changed due to your configuration (e.g. the directory or ``vfat`` instead of ``ext4`` for the file system). 39 | 40 | After a **reboot**, you should now be able to permanently access the ("any") USB drive plugged into your RPi via ``/home/pi/usb``. 41 | 42 | 43 | Remote Repository on the RPi 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | Now that we have a proper storage device configured, we can **add a remote repository** to an existing one (I assume you are working with Git already and have a few repositories to use now; if not see below). 47 | 48 | In my case, I take the repository of this tutorial which you can also find under http://github.com/yhilpisch/rpi as an example. Now do **on the RPi** the following:: 49 | 50 | cd /home/pi/usb 51 | mkdir rpi.git 52 | cd rpi.git 53 | git init --bare 54 | 55 | Then navigate on your **local machine** to the Git repository you want to push to the remote RPi location and do (cf. also :ref:`fixip` for the domain name):: 56 | 57 | git remote add rpi pi@rpi.mydomain.net:/home/pi/usb/rpi.git 58 | 59 | Then, you should be able to do something like:: 60 | 61 | git push rpi master 62 | 63 | You can then, for instance, **clone the repository** to some other location via:: 64 | 65 | git clone pi@rpi.mydomain.net:/home/pi/usb/rpi.git 66 | 67 | Of course, you can also generate a **new user**, say ``git``, whose credentials you can easily and safely share with members of your team or with friends. You only have to make sure that this new user has read (or even maybe write) rights to the respective Git repository/folder (e.g. ``sudo chmod -R 755 /home/pi/usb/rpi``). 68 | 69 | 70 | Generating Local Git Repository 71 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 72 | 73 | If you **do not have** an example **Git repository** (but Git installed locally), you can do the following steps **locally** (assuming the the remote location was set up as above):: 74 | 75 | mkdir rpi 76 | cd rpi 77 | git init 78 | # copy now some files into the the new directory 79 | git add --all . 80 | git commit -am 'Initial commit message.' 81 | git remote add rpi pi@rpi.mydomain.net:/home/pi/usb/rpi.git 82 | git push rpi master 83 | -------------------------------------------------------------------------------- /doc/build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 8 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 9 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 10 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 11 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 14 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 15 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 16 | .highlight .go { color: #333333 } /* Generic.Output */ 17 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 18 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 19 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 20 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 21 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 22 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 23 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 24 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 25 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #902000 } /* Keyword.Type */ 27 | .highlight .m { color: #208050 } /* Literal.Number */ 28 | .highlight .s { color: #4070a0 } /* Literal.String */ 29 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 30 | .highlight .nb { color: #007020 } /* Name.Builtin */ 31 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #60add5 } /* Name.Constant */ 33 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 34 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 35 | .highlight .ne { color: #007020 } /* Name.Exception */ 36 | .highlight .nf { color: #06287e } /* Name.Function */ 37 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 38 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 39 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 40 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 41 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 42 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 44 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 45 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 46 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 47 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 48 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 49 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 50 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 51 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 52 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 53 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 54 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 55 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 56 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 57 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 58 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 59 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 60 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 61 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 62 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /doc/build/latex/sphinxmanual.cls: -------------------------------------------------------------------------------- 1 | % 2 | % sphinxmanual.cls for Sphinx (http://sphinx-doc.org/) 3 | % 4 | 5 | \NeedsTeXFormat{LaTeX2e}[1995/12/01] 6 | \ProvidesClass{sphinxmanual}[2009/06/02 Document class (Sphinx manual)] 7 | 8 | % chapters starting at odd pages (overridden by 'openany' document option) 9 | \PassOptionsToClass{openright}{\sphinxdocclass} 10 | 11 | % 'oneside' option overriding the 'twoside' default 12 | \newif\if@oneside 13 | \DeclareOption{oneside}{\@onesidetrue} 14 | % Pass remaining document options to the parent class. 15 | \DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}} 16 | \ProcessOptions\relax 17 | 18 | % Defaults two-side document 19 | \if@oneside 20 | % nothing to do (oneside is the default) 21 | \else 22 | \PassOptionsToClass{twoside}{\sphinxdocclass} 23 | \fi 24 | 25 | \LoadClass{\sphinxdocclass} 26 | 27 | % Set some sane defaults for section numbering depth and TOC depth. You can 28 | % reset these counters in your preamble. 29 | % 30 | \setcounter{secnumdepth}{2} 31 | \setcounter{tocdepth}{1} 32 | 33 | % Change the title page to look a bit better, and fit in with the fncychap 34 | % ``Bjarne'' style a bit better. 35 | % 36 | \renewcommand{\maketitle}{% 37 | \begin{titlepage}% 38 | \let\footnotesize\small 39 | \let\footnoterule\relax 40 | \rule{\textwidth}{1pt}% 41 | \ifsphinxpdfoutput 42 | \begingroup 43 | % These \defs are required to deal with multi-line authors; it 44 | % changes \\ to ', ' (comma-space), making it pass muster for 45 | % generating document info in the PDF file. 46 | \def\\{, } 47 | \def\and{and } 48 | \pdfinfo{ 49 | /Author (\@author) 50 | /Title (\@title) 51 | } 52 | \endgroup 53 | \fi 54 | \begin{flushright}% 55 | \sphinxlogo% 56 | {\rm\Huge\py@HeaderFamily \@title \par}% 57 | {\em\LARGE\py@HeaderFamily \py@release\releaseinfo \par} 58 | \vfill 59 | {\LARGE\py@HeaderFamily 60 | \begin{tabular}[t]{c} 61 | \@author 62 | \end{tabular} 63 | \par} 64 | \vfill\vfill 65 | {\large 66 | \@date \par 67 | \vfill 68 | \py@authoraddress \par 69 | }% 70 | \end{flushright}%\par 71 | \@thanks 72 | \end{titlepage}% 73 | \cleardoublepage% 74 | \setcounter{footnote}{0}% 75 | \let\thanks\relax\let\maketitle\relax 76 | %\gdef\@thanks{}\gdef\@author{}\gdef\@title{} 77 | } 78 | 79 | 80 | % Catch the end of the {abstract} environment, but here make sure the abstract 81 | % is followed by a blank page if the 'openright' option is used. 82 | % 83 | \let\py@OldEndAbstract=\endabstract 84 | \renewcommand{\endabstract}{ 85 | \if@openright 86 | \ifodd\value{page} 87 | \typeout{Adding blank page after the abstract.} 88 | \vfil\pagebreak 89 | \fi 90 | \fi 91 | \py@OldEndAbstract 92 | } 93 | 94 | % This wraps the \tableofcontents macro with all the magic to get the spacing 95 | % right and have the right number of pages if the 'openright' option has been 96 | % used. This eliminates a fair amount of crud in the individual document files. 97 | % 98 | \let\py@OldTableofcontents=\tableofcontents 99 | \renewcommand{\tableofcontents}{% 100 | \pagenumbering{roman}% 101 | \setcounter{page}{1}% 102 | \pagebreak% 103 | \pagestyle{plain}% 104 | {% 105 | \parskip = 0mm% 106 | \py@OldTableofcontents% 107 | \if@openright% 108 | \ifodd\value{page}% 109 | \typeout{Adding blank page after the table of contents.}% 110 | \pagebreak\hspace{0pt}% 111 | \fi% 112 | \fi% 113 | \cleardoublepage% 114 | }% 115 | \pagenumbering{arabic}% 116 | \@ifundefined{fancyhf}{}{\pagestyle{normal}}% 117 | } 118 | \pagenumbering{alph} 119 | 120 | % This is needed to get the width of the section # area wide enough in the 121 | % library reference. Doing it here keeps it the same for all the manuals. 122 | % 123 | \renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}} 124 | \renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}} 125 | 126 | % Fix the bibliography environment to add an entry to the Table of 127 | % Contents. 128 | % For a report document class this environment is a chapter. 129 | \let\py@OldThebibliography=\thebibliography 130 | \renewcommand{\thebibliography}[1]{ 131 | \cleardoublepage 132 | \phantomsection 133 | \py@OldThebibliography{1} 134 | \addcontentsline{toc}{chapter}{\bibname} 135 | } 136 | 137 | % Same for the indices. 138 | % The memoir class already does this, so we don't duplicate it in that case. 139 | % 140 | \@ifclassloaded{memoir}{}{ 141 | \let\py@OldTheindex=\theindex 142 | \renewcommand{\theindex}{ 143 | \cleardoublepage 144 | \phantomsection 145 | \py@OldTheindex 146 | \addcontentsline{toc}{chapter}{\indexname} 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /doc/build/html/_static/sidebar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sidebar.js 3 | * ~~~~~~~~~~ 4 | * 5 | * This script makes the Sphinx sidebar collapsible. 6 | * 7 | * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds 8 | * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton 9 | * used to collapse and expand the sidebar. 10 | * 11 | * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden 12 | * and the width of the sidebar and the margin-left of the document 13 | * are decreased. When the sidebar is expanded the opposite happens. 14 | * This script saves a per-browser/per-session cookie used to 15 | * remember the position of the sidebar among the pages. 16 | * Once the browser is closed the cookie is deleted and the position 17 | * reset to the default (expanded). 18 | * 19 | * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. 20 | * :license: BSD, see LICENSE for details. 21 | * 22 | */ 23 | 24 | $(function() { 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | // global elements used by the functions. 34 | // the 'sidebarbutton' element is defined as global after its 35 | // creation, in the add_sidebar_button function 36 | var bodywrapper = $('.bodywrapper'); 37 | var sidebar = $('.sphinxsidebar'); 38 | var sidebarwrapper = $('.sphinxsidebarwrapper'); 39 | 40 | // for some reason, the document has no sidebar; do not run into errors 41 | if (!sidebar.length) return; 42 | 43 | // original margin-left of the bodywrapper and width of the sidebar 44 | // with the sidebar expanded 45 | var bw_margin_expanded = bodywrapper.css('margin-left'); 46 | var ssb_width_expanded = sidebar.width(); 47 | 48 | // margin-left of the bodywrapper and width of the sidebar 49 | // with the sidebar collapsed 50 | var bw_margin_collapsed = '.8em'; 51 | var ssb_width_collapsed = '.8em'; 52 | 53 | // colors used by the current theme 54 | var dark_color = $('.related').css('background-color'); 55 | var light_color = $('.document').css('background-color'); 56 | 57 | function sidebar_is_collapsed() { 58 | return sidebarwrapper.is(':not(:visible)'); 59 | } 60 | 61 | function toggle_sidebar() { 62 | if (sidebar_is_collapsed()) 63 | expand_sidebar(); 64 | else 65 | collapse_sidebar(); 66 | } 67 | 68 | function collapse_sidebar() { 69 | sidebarwrapper.hide(); 70 | sidebar.css('width', ssb_width_collapsed); 71 | bodywrapper.css('margin-left', bw_margin_collapsed); 72 | sidebarbutton.css({ 73 | 'margin-left': '0', 74 | 'height': bodywrapper.height() 75 | }); 76 | sidebarbutton.find('span').text('»'); 77 | sidebarbutton.attr('title', _('Expand sidebar')); 78 | document.cookie = 'sidebar=collapsed'; 79 | } 80 | 81 | function expand_sidebar() { 82 | bodywrapper.css('margin-left', bw_margin_expanded); 83 | sidebar.css('width', ssb_width_expanded); 84 | sidebarwrapper.show(); 85 | sidebarbutton.css({ 86 | 'margin-left': ssb_width_expanded-12, 87 | 'height': bodywrapper.height() 88 | }); 89 | sidebarbutton.find('span').text('«'); 90 | sidebarbutton.attr('title', _('Collapse sidebar')); 91 | document.cookie = 'sidebar=expanded'; 92 | } 93 | 94 | function add_sidebar_button() { 95 | sidebarwrapper.css({ 96 | 'float': 'left', 97 | 'margin-right': '0', 98 | 'width': ssb_width_expanded - 28 99 | }); 100 | // create the button 101 | sidebar.append( 102 | '
«
' 103 | ); 104 | var sidebarbutton = $('#sidebarbutton'); 105 | light_color = sidebarbutton.css('background-color'); 106 | // find the height of the viewport to center the '<<' in the page 107 | var viewport_height; 108 | if (window.innerHeight) 109 | viewport_height = window.innerHeight; 110 | else 111 | viewport_height = $(window).height(); 112 | sidebarbutton.find('span').css({ 113 | 'display': 'block', 114 | 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 115 | }); 116 | 117 | sidebarbutton.click(toggle_sidebar); 118 | sidebarbutton.attr('title', _('Collapse sidebar')); 119 | sidebarbutton.css({ 120 | 'color': '#FFFFFF', 121 | 'border-left': '1px solid ' + dark_color, 122 | 'font-size': '1.2em', 123 | 'cursor': 'pointer', 124 | 'height': bodywrapper.height(), 125 | 'padding-top': '1px', 126 | 'margin-left': ssb_width_expanded - 12 127 | }); 128 | 129 | sidebarbutton.hover( 130 | function () { 131 | $(this).css('background-color', dark_color); 132 | }, 133 | function () { 134 | $(this).css('background-color', light_color); 135 | } 136 | ); 137 | } 138 | 139 | function set_position_from_cookie() { 140 | if (!document.cookie) 141 | return; 142 | var items = document.cookie.split(';'); 143 | for(var k=0; k