├── shaolin ├── helpers.py ├── dashboards │ ├── __init__.py │ ├── context.py │ ├── data_transforms.py │ └── bokeh.py ├── .spyderproject ├── __pycache__ │ └── __init__.cpython-35.pyc ├── __init__.py └── core │ ├── __init__.py │ ├── context.py │ ├── dashboard.py │ ├── stateless_dashboard.py │ ├── widgets.py │ ├── kungfu.py │ └── shaoscript.py ├── tests ├── __init__.py ├── context.py ├── test_advanced.py └── test_basic.py ├── setup.cfg ├── docs ├── _build │ ├── html │ │ ├── _static │ │ │ ├── custom.css │ │ │ ├── up.png │ │ │ ├── down.png │ │ │ ├── file.png │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── comment.png │ │ │ ├── ajax-loader.gif │ │ │ ├── up-pressed.png │ │ │ ├── comment-close.png │ │ │ ├── down-pressed.png │ │ │ ├── comment-bright.png │ │ │ ├── pygments.css │ │ │ ├── doctools.js │ │ │ ├── underscore.js │ │ │ ├── alabaster.css │ │ │ └── basic.css │ │ ├── objects.inv │ │ ├── .buildinfo │ │ ├── searchindex.js │ │ ├── _sources │ │ │ └── index.txt │ │ ├── genindex.html │ │ ├── search.html │ │ └── index.html │ └── doctrees │ │ ├── index.doctree │ │ └── environment.pickle ├── .spyderproject ├── index.rst ├── make.bat ├── Makefile └── conf.py ├── requirements.txt ├── Makefile ├── requirements-dev.txt ├── examples ├── array_scaler.pkl ├── syntax_color.png ├── colors_data │ ├── img_1.png │ ├── img_2.png │ ├── seq_pal.png │ ├── cb_palette.png │ ├── sea_palette.png │ ├── new_cmappicker.png │ └── cubehelix_palette.png ├── gplot_data │ ├── layout.png │ ├── widget.png │ ├── pmfg_box.png │ ├── tooltip.png │ ├── full_plot.png │ ├── high_pmfg.png │ ├── edge_display.png │ ├── node_display.png │ ├── sample_matrix_panel.h5 │ └── sample_node_metrics.h5 ├── scatter_data │ ├── free.png │ ├── img_1.png │ ├── img_2.png │ ├── img_3.png │ ├── img_4.png │ ├── mapper.png │ ├── scale.png │ ├── widget.png │ ├── overlap.png │ ├── structure.dia │ ├── structure.png │ ├── tooltip.png │ ├── simple_scatter.png │ └── structure.svg ├── dashboards_data │ ├── img_1.png │ ├── img_2.png │ ├── img_3.png │ ├── img_4.png │ └── img_5.png ├── gcalculator_data │ ├── img_1.png │ ├── layout.png │ ├── matrix.png │ ├── widget.png │ ├── creation.png │ └── forex_sample.h5 ├── auto_dashboard_data │ ├── image_1.png │ ├── image_2.png │ ├── image_3.png │ ├── image_4.png │ ├── image_5.png │ ├── image_6.png │ └── image_7.png ├── shaolin_syntax_data │ ├── img_1.png │ ├── img_10.png │ ├── img_11.png │ ├── img_2.png │ ├── img_3.png │ ├── img_4.png │ ├── img_5.png │ ├── img_6.png │ ├── img_7.png │ ├── img_8.png │ ├── img_9.png │ ├── mem_1.png │ ├── mem_10.png │ ├── mem_11.png │ ├── mem_2.png │ ├── mem_3.png │ ├── mem_4.png │ ├── mem_5.png │ ├── mem_6.png │ ├── mem_7.png │ ├── mem_8.png │ └── mem_9.png ├── complex_dashboards_data │ ├── img_1.png │ ├── img_2.png │ └── img_3.png └── Untitled.ipynb ├── setup.py └── README.md /shaolin/helpers.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /shaolin/dashboards/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | -------------------------------------------------------------------------------- /docs/_build/html/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pandas >= 0.18.0 2 | numpy >= 1.11.0 3 | ipywidgets > 4.1.1 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | init: 2 | pip install -r requirements.txt 3 | 4 | test: 5 | nosetests tests 6 | -------------------------------------------------------------------------------- /docs/.spyderproject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/.spyderproject -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | 2 | pandas >= 0.18.0 3 | numpy >= 1.11.0 4 | ipywidgets > 4.1.1 5 | -------------------------------------------------------------------------------- /shaolin/.spyderproject: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/shaolin/.spyderproject -------------------------------------------------------------------------------- /examples/array_scaler.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/array_scaler.pkl -------------------------------------------------------------------------------- /examples/syntax_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/syntax_color.png -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /examples/colors_data/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/img_1.png -------------------------------------------------------------------------------- /examples/colors_data/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/img_2.png -------------------------------------------------------------------------------- /examples/gplot_data/layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/layout.png -------------------------------------------------------------------------------- /examples/gplot_data/widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/widget.png -------------------------------------------------------------------------------- /examples/scatter_data/free.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/free.png -------------------------------------------------------------------------------- /docs/_build/html/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/up.png -------------------------------------------------------------------------------- /examples/colors_data/seq_pal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/seq_pal.png -------------------------------------------------------------------------------- /examples/gplot_data/pmfg_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/pmfg_box.png -------------------------------------------------------------------------------- /examples/gplot_data/tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/tooltip.png -------------------------------------------------------------------------------- /examples/scatter_data/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/img_1.png -------------------------------------------------------------------------------- /examples/scatter_data/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/img_2.png -------------------------------------------------------------------------------- /examples/scatter_data/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/img_3.png -------------------------------------------------------------------------------- /examples/scatter_data/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/img_4.png -------------------------------------------------------------------------------- /examples/scatter_data/mapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/mapper.png -------------------------------------------------------------------------------- /examples/scatter_data/scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/scale.png -------------------------------------------------------------------------------- /examples/scatter_data/widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/widget.png -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/down.png -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /examples/colors_data/cb_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/cb_palette.png -------------------------------------------------------------------------------- /examples/dashboards_data/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/dashboards_data/img_1.png -------------------------------------------------------------------------------- /examples/dashboards_data/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/dashboards_data/img_2.png -------------------------------------------------------------------------------- /examples/dashboards_data/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/dashboards_data/img_3.png -------------------------------------------------------------------------------- /examples/dashboards_data/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/dashboards_data/img_4.png -------------------------------------------------------------------------------- /examples/dashboards_data/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/dashboards_data/img_5.png -------------------------------------------------------------------------------- /examples/gcalculator_data/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gcalculator_data/img_1.png -------------------------------------------------------------------------------- /examples/gplot_data/full_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/full_plot.png -------------------------------------------------------------------------------- /examples/gplot_data/high_pmfg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/high_pmfg.png -------------------------------------------------------------------------------- /examples/scatter_data/overlap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/overlap.png -------------------------------------------------------------------------------- /examples/scatter_data/structure.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/structure.dia -------------------------------------------------------------------------------- /examples/scatter_data/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/structure.png -------------------------------------------------------------------------------- /examples/scatter_data/tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/tooltip.png -------------------------------------------------------------------------------- /docs/_build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/comment.png -------------------------------------------------------------------------------- /examples/colors_data/sea_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/sea_palette.png -------------------------------------------------------------------------------- /examples/gcalculator_data/layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gcalculator_data/layout.png -------------------------------------------------------------------------------- /examples/gcalculator_data/matrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gcalculator_data/matrix.png -------------------------------------------------------------------------------- /examples/gcalculator_data/widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gcalculator_data/widget.png -------------------------------------------------------------------------------- /examples/gplot_data/edge_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/edge_display.png -------------------------------------------------------------------------------- /examples/gplot_data/node_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/node_display.png -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/_build/html/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/up-pressed.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_1.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_2.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_3.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_4.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_5.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_6.png -------------------------------------------------------------------------------- /examples/auto_dashboard_data/image_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/auto_dashboard_data/image_7.png -------------------------------------------------------------------------------- /examples/colors_data/new_cmappicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/new_cmappicker.png -------------------------------------------------------------------------------- /examples/gcalculator_data/creation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gcalculator_data/creation.png -------------------------------------------------------------------------------- /examples/scatter_data/simple_scatter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/scatter_data/simple_scatter.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_1.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_10.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_11.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_2.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_3.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_4.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_5.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_6.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_7.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_8.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/img_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/img_9.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_1.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_10.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_11.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_2.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_3.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_4.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_5.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_6.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_7.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_8.png -------------------------------------------------------------------------------- /examples/shaolin_syntax_data/mem_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/shaolin_syntax_data/mem_9.png -------------------------------------------------------------------------------- /docs/_build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/comment-close.png -------------------------------------------------------------------------------- /docs/_build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /examples/colors_data/cubehelix_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/colors_data/cubehelix_palette.png -------------------------------------------------------------------------------- /examples/complex_dashboards_data/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/complex_dashboards_data/img_1.png -------------------------------------------------------------------------------- /examples/complex_dashboards_data/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/complex_dashboards_data/img_2.png -------------------------------------------------------------------------------- /examples/complex_dashboards_data/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/complex_dashboards_data/img_3.png -------------------------------------------------------------------------------- /examples/gcalculator_data/forex_sample.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gcalculator_data/forex_sample.h5 -------------------------------------------------------------------------------- /examples/gplot_data/sample_matrix_panel.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/sample_matrix_panel.h5 -------------------------------------------------------------------------------- /examples/gplot_data/sample_node_metrics.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/examples/gplot_data/sample_node_metrics.h5 -------------------------------------------------------------------------------- /docs/_build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/docs/_build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /shaolin/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HCsoft-RD/shaolin/HEAD/shaolin/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /tests/context.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import sys 4 | import os 5 | sys.path.insert(0, os.path.abspath('..')) 6 | 7 | import sample -------------------------------------------------------------------------------- /shaolin/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from shaolin.core.dashboard import Dashboard 3 | from shaolin.core.kungfu import KungFu 4 | from shaolin.core.shaoscript import shaoscript 5 | -------------------------------------------------------------------------------- /shaolin/core/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Jun 6 21:41:19 2016 4 | 5 | @author: Guillem Duran Ballester for HCSOFT 6 | 7 | """ 8 | 9 | -------------------------------------------------------------------------------- /docs/_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: 983c11a0d6ff48a0c8f5fcdbb6e00ab5 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({envversion:48,filenames:["index"],objects:{},objnames:{},objtypes:{},terms:{content:0,index:0,modul:0,page:0,search:0},titles:["Welcome to Shaolin’s documentation!"],titleterms:{document:0,indic:0,shaolin:0,tabl:0,welcom:0}}) -------------------------------------------------------------------------------- /tests/test_advanced.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .context import sample 4 | 5 | import unittest 6 | 7 | 8 | class AdvancedTestSuite(unittest.TestCase): 9 | """Advanced test cases.""" 10 | 11 | def test_thoughts(self): 12 | sample.hmm() 13 | 14 | 15 | if __name__ == '__main__': 16 | unittest.main() -------------------------------------------------------------------------------- /tests/test_basic.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .context import sample 4 | 5 | import unittest 6 | 7 | 8 | class BasicTestSuite(unittest.TestCase): 9 | """Basic test cases.""" 10 | 11 | def test_absolute_truth_and_meaning(self): 12 | assert True 13 | 14 | 15 | if __name__ == '__main__': 16 | unittest.main() -------------------------------------------------------------------------------- /shaolin/core/context.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu May 19 12:06:56 2016 4 | 5 | @author: Guillem Duran Ballester 6 | """ 7 | 8 | 9 | from shaolin.core.widgets import Widget, Title, SubTitle, SubSubTitle 10 | 11 | from shaolin.core import dashboard 12 | #from shaolin.widgets.dashboards import ToggleMenu 13 | #from shaolin.shaoscript.shaoscript import shaoscript -------------------------------------------------------------------------------- /shaolin/dashboards/context.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu May 19 12:10:57 2016 4 | 5 | @author: sergio 6 | """ 7 | 8 | 9 | from shaolin.shaolin.widgets import Widget 10 | #from .dashboards import ToggleMenu 11 | from shaolin.core.dashboard import Dashboard 12 | from shaolin.core.stateless_dashboard import StatelessDashboard 13 | from shaolin.core.css import LayoutHacker -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Shaolin documentation master file, created by 2 | sphinx-quickstart on Sun May 8 20:56:25 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Shaolin's documentation! 7 | =================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | 15 | 16 | Indices and tables 17 | ================== 18 | 19 | * :ref:`genindex` 20 | * :ref:`modindex` 21 | * :ref:`search` 22 | 23 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/index.txt: -------------------------------------------------------------------------------- 1 | .. Shaolin documentation master file, created by 2 | sphinx-quickstart on Sun May 8 20:56:25 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Shaolin's documentation! 7 | =================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | 15 | 16 | Indices and tables 17 | ================== 18 | 19 | * :ref:`genindex` 20 | * :ref:`modindex` 21 | * :ref:`search` 22 | 23 | -------------------------------------------------------------------------------- /examples/Untitled.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [] 11 | } 12 | ], 13 | "metadata": { 14 | "kernelspec": { 15 | "display_name": "Python 3", 16 | "language": "python", 17 | "name": "python3" 18 | }, 19 | "language_info": { 20 | "codemirror_mode": { 21 | "name": "ipython", 22 | "version": 3 23 | }, 24 | "file_extension": ".py", 25 | "mimetype": "text/x-python", 26 | "name": "python", 27 | "nbconvert_exporter": "python", 28 | "pygments_lexer": "ipython3", 29 | "version": "3.5.1" 30 | }, 31 | "widgets": { 32 | "state": {}, 33 | "version": "1.1.2" 34 | } 35 | }, 36 | "nbformat": 4, 37 | "nbformat_minor": 0 38 | } 39 | -------------------------------------------------------------------------------- /docs/_build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index — Shaolin 0.0.1 documentation 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 |
40 |
41 |
42 | 43 | 44 |

Index

45 | 46 |
47 | 48 |
49 | 50 | 51 |
52 |
53 |
54 | 77 |
78 |
79 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """A setuptools based setup module. 3 | See: 4 | https://packaging.python.org/en/latest/distributing.html 5 | https://github.com/pypa/sampleproject 6 | """ 7 | 8 | # Always prefer setuptools over distutils 9 | from setuptools import setup, find_packages 10 | # To use a consistent encoding 11 | from codecs import open 12 | from os import path 13 | 14 | here = path.abspath(path.dirname(__file__)) 15 | 16 | # Get the long description from the README file 17 | with open(path.join(here, 'README.md'), encoding='utf-8') as f: 18 | long_description = f.read() 19 | 20 | setup( 21 | name='shaolin', 22 | 23 | # Versions should comply with PEP440. For a discussion on single-sourcing 24 | # the version across setup.py and the project code, see 25 | # https://packaging.python.org/en/latest/single_source_version.html 26 | version='0.0.1b2', 27 | 28 | description='Interactive dashboard programming framework for the jupyter notebook', 29 | long_description=long_description, 30 | 31 | # The project's main homepage. 32 | url='https://github.com/HCsoft-RD/shaolin', 33 | 34 | # Author details 35 | author='HCSoft programacion S.L. (coded by Guillem Duran Ballester)', 36 | author_email='oficina@hcsoft.net', 37 | 38 | # Choose your license 39 | license='BSD', 40 | 41 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers 42 | classifiers=[ 43 | # How mature is this project? Common values are 44 | # 3 - Alpha 45 | # 4 - Beta 46 | # 5 - Production/Stable 47 | 'Development Status :: 4 - Beta', 48 | 49 | # Indicate who your project is intended for 50 | 'Intended Audience :: Developers', 51 | 'Topic :: Software Development :: Build Tools', 52 | 53 | # Pick your license as you wish (should match "license" above) 54 | 'License :: OSI Approved :: BSD License', 55 | 56 | # Specify the Python versions you support here. In particular, ensure 57 | # that you indicate whether you support Python 2, Python 3 or both. 58 | 'Programming Language :: Python :: 3', 59 | 'Programming Language :: Python :: 3.3', 60 | 'Programming Language :: Python :: 3.4', 61 | 'Programming Language :: Python :: 3.5', 62 | 'Programming Language :: Python :: 3.6', 63 | ], 64 | 65 | # What does your project relate to? 66 | keywords=['dashboards', 'data vis', 'data analysis', 'shaolin'], 67 | 68 | # You can just specify the packages manually here if your project is 69 | # simple. Or you can use find_packages(). 70 | packages=find_packages(exclude=['contrib', 'docs', 'tests']), 71 | 72 | # Alternatively, if you want to distribute just a my_module.py, uncomment 73 | # this: 74 | # py_modules=["my_module"], 75 | 76 | # List run-time dependencies here. These will be installed by pip when 77 | # your project is installed. For an analysis of "install_requires" vs pip's 78 | # requirements files see: 79 | # https://packaging.python.org/en/latest/requirements.html 80 | install_requires=['planarity','bokeh', 'pandas', 'numpy', 81 | 'networkx', 'seaborn','ipywidgets','plotly','cufflinks'], 82 | 83 | # List additional groups of dependencies here (e.g. development 84 | # dependencies). You can install these using the following syntax, 85 | # for example: 86 | # $ pip install -e .[dev,test] 87 | extras_require={ 88 | 'dev': ['check-manifest'], 89 | 'test': ['coverage'], 90 | } 91 | 92 | ) 93 | 94 | 95 | -------------------------------------------------------------------------------- /docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Search — Shaolin 0.0.1 documentation 10 | 11 | 12 | 13 | 14 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 |
48 |
49 | 50 |

Search

51 |
52 | 53 |

54 | Please activate JavaScript to enable the search 55 | functionality. 56 |

57 |
58 |

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

64 |
65 | 66 | 67 | 68 |
69 | 70 |
71 | 72 |
73 | 74 |
75 |
76 |
77 | 87 |
88 |
89 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /shaolin/dashboards/data_transforms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Jun 1 23:31:50 2016 4 | 5 | @author: Guillem Duran Ballester for HCSoft 6 | """ 7 | import numpy as np 8 | import pandas as pd 9 | from shaolin.core.dashboard import Dashboard 10 | class DataFrameScaler(Dashboard): 11 | 12 | def __init__(self, 13 | data, 14 | funcs=None, 15 | min=0, 16 | max=100, 17 | step=None, 18 | low=None, 19 | high=None, 20 | **kwargs): 21 | if funcs is None: 22 | self.funcs = {'raw':lambda x: x, 23 | 'zscore': lambda x: (x-np.mean(x))/np.std(x), 24 | 'log': np.log, 25 | 'rank':lambda x: pd.DataFrame(x).rank().values.flatten(), 26 | 'inv': lambda x: -x, 27 | 'cut':lambda x: pd.cut(x,[-1001, 0.1,0.3, 0.6, 0.8, 1.0,1.5, 3.0, 6.0, 12, 1001],labels=False) 28 | } 29 | else: 30 | self.funcs = funcs 31 | self._df = data.apply(self.categorical_to_num) 32 | if min is None: 33 | min = self._df.min().values[0] 34 | if max is None: 35 | max = self._df.max().values[0] 36 | if step is None: 37 | step = (max-min)/100. 38 | if low is None: 39 | low = min 40 | if high is None: 41 | high = max 42 | 43 | self.output = None 44 | 45 | dash = ['c$N=df_scaler', 46 | ['@('+str(min)+', '+str(max)+', '+str(step)+', ('+str(low)+', '+str(high)+'))$N=scale_slider&d=Scale', 47 | ['r$N=main_row',['@dd$d=Apply&N=dd_sel&val=raw&o='+str(list(self.funcs.keys())),'@True$N=scale_chk&d=Scale']] 48 | ] 49 | ] 50 | Dashboard.__init__(self, dash, mode='interactive', **kwargs) 51 | self.dd_sel.target.layout.width = "100%" 52 | self.scale_chk.widget.layout.padding = "0.25em" 53 | self.observe(self.update) 54 | self.update() 55 | 56 | @property 57 | def data(self): 58 | return self._df 59 | 60 | @data.setter 61 | def data(self, val): 62 | self._df = val.apply(self.categorical_to_num) 63 | self.update() 64 | 65 | def scale_func(self, data): 66 | Ma = np.max(data) 67 | mi = np.min(data) 68 | score = ((data-mi)/(Ma-mi))#to 0-1 interval 69 | if mi == Ma: 70 | return np.ones(len(score)) *0.5 71 | scale_h = self.scale_slider.value[1] 72 | scale_l = self.scale_slider.value[0] 73 | return score*(scale_h-scale_l)+scale_l 74 | 75 | def update(self, _=None): 76 | self.output = self.data.apply(self.funcs[self.dd_sel.value]) 77 | if self.scale_chk.value: 78 | self.scale_slider.visible = True 79 | self.output = self.output.apply(self.scale_func) 80 | else: 81 | self.scale_slider.visible = False 82 | @staticmethod 83 | def categorical_to_num(data): 84 | """Converts categorical data into an array of ints""" 85 | if isinstance(data.values[0], str): 86 | cats = np.unique(data) 87 | imap = {} 88 | for i, cat in enumerate(cats): 89 | imap[cat] = i 90 | fun = lambda x: imap[x] 91 | return list(map(fun, data)) 92 | else: 93 | return data 94 | 95 | @staticmethod 96 | def is_categorical_series(data): 97 | """true if data is a categorical series""" 98 | return isinstance(data.values[0], str) 99 | -------------------------------------------------------------------------------- /docs/_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 .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 51 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 52 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 53 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 54 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 55 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 56 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 57 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 58 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 59 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 60 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 61 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 62 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 63 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 64 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 65 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_build/html/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Welcome to Shaolin’s documentation! — Shaolin 0.0.1 documentation 10 | 11 | 12 | 13 | 14 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 |
40 |
41 | 42 |
43 |

Welcome to Shaolin’s documentation!

44 |

Contents:

45 |
46 |
    47 |
48 |
49 |
50 |
51 |

Indices and tables

52 | 57 |
58 | 59 | 60 |
61 |
62 |
63 | 96 |
97 |
98 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Shaolin 3 | 4 | 5 | ## Framework for interactive widget-based dashboards programming. Feedback is really appreciated 6 | 7 | 8 | **Shaolin**(**S**tructure **H**elper for d**A**shb**O**ard **LIN**king) is an ipywidgets based framework that allows to create interactive dashboards that can be linked with each other to build complex applications. 9 | 10 | Its still in a alpha alpha version, the beta version will be realeased before 17 july. 11 | 12 | Installation: **pip install shaolin**. 13 | 14 | ## Alpha version disclaimer 15 | 16 | This package is a few months old and has only been tested by me. Everything should work with medium size data (Pandas and plotting using the svg backend instead of WebGL). If you plan on using shaolin for business please contact me. 17 | 18 | ### Dependencies: 19 | - six 20 | - numpy 21 | - pandas 22 | - planarity 23 | - networkx 24 | - bokeh 25 | - seaborn 26 | - vpython 27 | - plotly 28 | - cufflinks 29 | 30 | 31 | 32 | 33 | # Main features 34 | 35 | 36 | The documentation is located in the [examples](https://github.com/HCsoft-RD/shaolin/tree/master/examples) folder. 37 | 38 | ### ipywidgets based and pydata compatible 39 | 40 | This framework is build on top of standard pydata libraries like pandas and numpy and uses only the ipywidgets package for the interface management, although 41 | shaolin provides a simplified interface that extends the ipywidgets capabilities. 42 | 43 | ### Own syntax for quickly defining new Dashboards 44 | 45 | Shaolin has a simplified syntax that allows to program dashboards consisting on multiple widgets more quickly. 46 | 47 | - [Syntax for defining widgets](https://github.com/HCsoft-RD/shaolin/blob/master/examples/Shaolin%20syntax.ipynb) 48 | - [Dashboard introduction](https://github.com/HCsoft-RD/shaolin/blob/master/examples/Dashboards.ipynb) 49 | 50 | ### Link different Dashboard to create complex applications 51 | 52 | It is possible to combine multiple dashboards into a new one in order to perform complex tasks like data analysis or plotting. 53 | 54 | - [Dashboard programming tutorial](https://github.com/HCsoft-RD/shaolin/blob/master/examples/Creating%20complex%20Dashboards.ipynb) 55 | 56 | ### Save and share your dashboards easily 57 | 58 | You can load and save the state of a dashboard easily with no additional effort. 59 | 60 | ### No more writing widgets css 61 | 62 | Modify any visual property of a dashboard interactively using widgets. 63 | 64 | 65 | ********************* 66 | # Sample Dashboards 67 | 68 | Shaolin comes batteries included with Dashboard created for performing various standard data analysis tasks that you can use as a base to build your own applications. 69 | 70 | ### Colormap creation 71 | Use a colormap picker capable of creating any matplotlib and seaborn colormap or palette. 72 | 73 | - [Colormap tutorial](https://github.com/HCsoft-RD/shaolin/blob/master/examples/Shaolin%20Colors.ipynb) 74 | 75 | ### Full customizable scatter plot 76 | 77 | Plot an interactive bokeh scatter plot with tooltips from any pandas DataFrame, Panel or Panel4D. You will be able to modify any visual property of the plot with just a few clicks. I bet you wont need to program another scatter plot after trying this ;) 78 | 79 | - [Scatter plot introduction](https://github.com/HCsoft-RD/shaolin/blob/master/examples/Scatter%20Plot%20introduction.ipynb) 80 | 81 | ### Networkx compatibility 82 | We have dashboards that map the networkx interface to calculate any graph metric, any graph layout and the capability of converting time series correlation matrices into graphs. 83 | You will also be able to plot any graph using the networkx capabilities in a fully customizable bokeh plot. 84 | 85 | - [Shaolin GraphCalculator tutorial] (https://github.com/HCsoft-RD/shaolin/blob/master/examples/GraphCalculator.ipynb) 86 | - [Shaolin Bokeh GraphPlot tutorial] (https://github.com/HCsoft-RD/shaolin/blob/master/examples/GraphPlot.ipynb) 87 | 88 | ### Slicers 89 | Widgets for slicing any pandas structure or numpy array. 90 | 91 | ###plot mappers 92 | These Dashboards provide everything you need to create new interactive plots with almost no code. 93 | 94 | ### Plotly compatibility 95 | Define a custom plot layout using widgets and use the cufflinks library with a pandas DataFrame without writing a single line of code. 96 | 97 | # Upcoming features 98 | 99 | I hope most of there are available in the beta release. 100 | 101 | ###Walkers 102 | 103 | It will extend the capabilities of the GraphCalculator for making interactive animated graphs in real time. This is really usefull for visualizing correlation matrix time series. 104 | 105 | 106 | Compatibility for mapping data to interactive matplotlib plots using MplD3. 107 | 108 | -------------------------------------------------------------------------------- /shaolin/core/dashboard.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu May 19 12:02:20 2016 4 | 5 | @author: Guillem Duran Ballester 6 | """ 7 | #import six 8 | #import pickle 9 | from shaolin.core import stateless_dashboard as sld 10 | #from .css import LayoutHacker 11 | 12 | class Dashboard(sld.StatelessDashboard): 13 | """Clash for managing arbitrary Dashboards""" 14 | def __init__(self,dash, state=None, **kwargs): 15 | sld.StatelessDashboard.__init__(self, dash, **kwargs) 16 | #self._state = self._load_state(state) 17 | 18 | def __call__(self,**kwargs): 19 | return self.kwargs 20 | def __getitem__(self,index): 21 | if index is None or isinstance(index,(int,bool)): 22 | return self.widget 23 | else: 24 | raise ValueError("index must be integer or None or bool") 25 | """" 26 | @property 27 | def state(self): 28 | return self._state 29 | @state.setter 30 | def state(self, val): 31 | self._state = val 32 | self.apply_state() 33 | def _update_state(self, _=None): 34 | self._state = self._state_manager.output 35 | 36 | def _load_state(self, state): 37 | if isinstance(state, six.string_types): 38 | try: 39 | with open(state, "rb") as input_file: 40 | state = pickle.load(input_file) 41 | except: 42 | return None 43 | if not state is None: 44 | self.apply_state(state) 45 | return state 46 | 47 | @property 48 | def kwargs(self): 49 | return StatelessDashboard.kwargs 50 | 51 | @kwargs.setter 52 | def kwargs(self,vals): 53 | Children values as a kwargs dict for easier interactivity 54 | 55 | for name in vals.keys(): 56 | attr = getattr(self, name) 57 | if isinstance(attr, Dashboard): 58 | attr.kwargs = vals['name'] 59 | else: 60 | attr.value = vals['name'] 61 | @property 62 | def state_manager(self): 63 | self._state_manager = LayoutHacker(self) 64 | self._state_manager.observe(self._update_state) 65 | self._update_state() 66 | return self._state_manager.widget 67 | 68 | def apply_state(self, state_dict=None): 69 | "loads a generated state dict and applies it to the dashboard" 70 | if state_dict is None: 71 | state_dict = self._state 72 | if state_dict is None: 73 | self.state_manager() 74 | for attr in self.mode_dict['all']: 75 | for css_tra, items_dict in state_dict[attr]['css_traits'].items(): 76 | for widget,val in items_dict.items(): 77 | layout = getattr(getattr(self, attr), widget).layout 78 | if val != '': 79 | setattr(layout,css_tra,val) 80 | for tget_attr, val in state_dict[attr]['widget_attrs'].items(): 81 | tget_wid = getattr(self, attr).target 82 | if val != '': 83 | setattr(tget_wid, tget_attr, val)""" 84 | 85 | class ToggleMenu(Dashboard): 86 | def __init__(self, 87 | children, 88 | description='', 89 | buttons_shao=None, 90 | name=None, 91 | button_labels=None, 92 | button_type='togs', 93 | button_pos='bottom', 94 | **kwargs): 95 | self.child_names = self.get_children_names(children) 96 | if button_labels is None: 97 | self.button_labels = self.child_names 98 | else: 99 | self.button_labels = button_labels 100 | 101 | if buttons_shao is None: 102 | opts = dict(zip(self.button_labels,self.child_names)) 103 | buttons_shao = ['@'+button_type+'$N=buttons&d='+str(description)+'&o='+str(opts)] 104 | 105 | self.children_dash = children 106 | #children = ['fs$d=fs','fs$d=fs2'] 107 | #buttons = ['r$n=buttons', buttons_shao] 108 | if button_pos == 'bottom': 109 | dash = ['V$n=toggleMenu', 110 | children+buttons_shao 111 | ] 112 | elif button_pos == 'top': 113 | dash = ['V$n=toggleMenu', 114 | buttons_shao+children 115 | ] 116 | elif button_pos == 'right': 117 | dash = ['r$n=toggleMenu', 118 | children+buttons_shao 119 | ] 120 | elif button_pos == 'left': 121 | dash = ['r$n=toggleMenu', 122 | buttons_shao+children 123 | ] 124 | Dashboard.__init__(self, dash, func=None, name=name, **kwargs) 125 | self.update_toggle() 126 | self.buttons.target.observe(self.update_toggle) 127 | 128 | def get_children_names(self,children): 129 | names = [] 130 | for c in children: 131 | try: 132 | names += [self.name_from_shaoscript(c)] 133 | except: 134 | names += [c.name] 135 | 136 | return names 137 | 138 | def update_toggle(self,_=None): 139 | 140 | for name in self.child_names: 141 | child = getattr(self,name) 142 | if name == self.buttons.value: 143 | child.visible = True 144 | else: 145 | child.visible = False -------------------------------------------------------------------------------- /examples/scatter_data/structure.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | pandas data 9 | 10 | 11 | 12 | 13 | 14 | 15 | Slicer 16 | 17 | 18 | 19 | 20 | 21 | 22 | Scaler 23 | 24 | 25 | 26 | 27 | 28 | 29 | Defaults 30 | 31 | 32 | 33 | 34 | 35 | 36 | Tooltip data 37 | 38 | 39 | 40 | 41 | 42 | 43 | output DataFrame 44 | 45 | 46 | 47 | 48 | Plot data mapper 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Bokeh source 75 | 76 | 77 | 78 | 79 | 80 | 81 | Plot 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s == 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node) { 70 | if (node.nodeType == 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { 74 | var span = document.createElement("span"); 75 | span.className = className; 76 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 77 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 78 | document.createTextNode(val.substr(pos + text.length)), 79 | node.nextSibling)); 80 | node.nodeValue = val.substr(0, pos); 81 | } 82 | } 83 | else if (!jQuery(node).is("button, select, textarea")) { 84 | jQuery.each(node.childNodes, function() { 85 | highlight(this); 86 | }); 87 | } 88 | } 89 | return this.each(function() { 90 | highlight(this); 91 | }); 92 | }; 93 | 94 | /* 95 | * backward compatibility for jQuery.browser 96 | * This will be supported until firefox bug is fixed. 97 | */ 98 | if (!jQuery.browser) { 99 | jQuery.uaMatch = function(ua) { 100 | ua = ua.toLowerCase(); 101 | 102 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 103 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 104 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 105 | /(msie) ([\w.]+)/.exec(ua) || 106 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 107 | []; 108 | 109 | return { 110 | browser: match[ 1 ] || "", 111 | version: match[ 2 ] || "0" 112 | }; 113 | }; 114 | jQuery.browser = {}; 115 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 116 | } 117 | 118 | /** 119 | * Small JavaScript module for the documentation. 120 | */ 121 | var Documentation = { 122 | 123 | init : function() { 124 | this.fixFirefoxAnchorBug(); 125 | this.highlightSearchWords(); 126 | this.initIndexTable(); 127 | }, 128 | 129 | /** 130 | * i18n support 131 | */ 132 | TRANSLATIONS : {}, 133 | PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, 134 | LOCALE : 'unknown', 135 | 136 | // gettext and ngettext don't access this so that the functions 137 | // can safely bound to a different name (_ = Documentation.gettext) 138 | gettext : function(string) { 139 | var translated = Documentation.TRANSLATIONS[string]; 140 | if (typeof translated == 'undefined') 141 | return string; 142 | return (typeof translated == 'string') ? translated : translated[0]; 143 | }, 144 | 145 | ngettext : function(singular, plural, n) { 146 | var translated = Documentation.TRANSLATIONS[singular]; 147 | if (typeof translated == 'undefined') 148 | return (n == 1) ? singular : plural; 149 | return translated[Documentation.PLURALEXPR(n)]; 150 | }, 151 | 152 | addTranslations : function(catalog) { 153 | for (var key in catalog.messages) 154 | this.TRANSLATIONS[key] = catalog.messages[key]; 155 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 156 | this.LOCALE = catalog.locale; 157 | }, 158 | 159 | /** 160 | * add context elements like header anchor links 161 | */ 162 | addContextElements : function() { 163 | $('div[id] > :header:first').each(function() { 164 | $('\u00B6'). 165 | attr('href', '#' + this.id). 166 | attr('title', _('Permalink to this headline')). 167 | appendTo(this); 168 | }); 169 | $('dt[id]').each(function() { 170 | $('\u00B6'). 171 | attr('href', '#' + this.id). 172 | attr('title', _('Permalink to this definition')). 173 | appendTo(this); 174 | }); 175 | }, 176 | 177 | /** 178 | * workaround a firefox stupidity 179 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 180 | */ 181 | fixFirefoxAnchorBug : function() { 182 | if (document.location.hash) 183 | window.setTimeout(function() { 184 | document.location.href += ''; 185 | }, 10); 186 | }, 187 | 188 | /** 189 | * highlight the search words provided in the url in the text 190 | */ 191 | highlightSearchWords : function() { 192 | var params = $.getQueryParameters(); 193 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 194 | if (terms.length) { 195 | var body = $('div.body'); 196 | if (!body.length) { 197 | body = $('body'); 198 | } 199 | window.setTimeout(function() { 200 | $.each(terms, function() { 201 | body.highlightText(this.toLowerCase(), 'highlighted'); 202 | }); 203 | }, 10); 204 | $('') 206 | .appendTo($('#searchbox')); 207 | } 208 | }, 209 | 210 | /** 211 | * init the domain index toggle buttons 212 | */ 213 | initIndexTable : function() { 214 | var togglers = $('img.toggler').click(function() { 215 | var src = $(this).attr('src'); 216 | var idnum = $(this).attr('id').substr(7); 217 | $('tr.cg-' + idnum).toggle(); 218 | if (src.substr(-9) == 'minus.png') 219 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 220 | else 221 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 222 | }).css('display', ''); 223 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 224 | togglers.click(); 225 | } 226 | }, 227 | 228 | /** 229 | * helper function to hide the search marks again 230 | */ 231 | hideSearchWords : function() { 232 | $('#searchbox .highlight-link').fadeOut(300); 233 | $('span.highlighted').removeClass('highlighted'); 234 | }, 235 | 236 | /** 237 | * make the url absolute 238 | */ 239 | makeURL : function(relativeURL) { 240 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 241 | }, 242 | 243 | /** 244 | * get the current relative url 245 | */ 246 | getCurrentURL : function() { 247 | var path = document.location.pathname; 248 | var parts = path.split(/\//); 249 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 250 | if (this == '..') 251 | parts.pop(); 252 | }); 253 | var url = parts.join('/'); 254 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 255 | } 256 | }; 257 | 258 | // quick alias for translations 259 | _ = Documentation.gettext; 260 | 261 | $(document).ready(function() { 262 | Documentation.init(); 263 | }); 264 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. epub3 to make an epub3 31 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 32 | echo. text to make text files 33 | echo. man to make manual pages 34 | echo. texinfo to make Texinfo files 35 | echo. gettext to make PO message catalogs 36 | echo. changes to make an overview over all changed/added/deprecated items 37 | echo. xml to make Docutils-native XML files 38 | echo. pseudoxml to make pseudoxml-XML files for display purposes 39 | echo. linkcheck to check all external links for integrity 40 | echo. doctest to run all doctests embedded in the documentation if enabled 41 | echo. coverage to run coverage check of the documentation if enabled 42 | echo. dummy to check syntax errors of document sources 43 | goto end 44 | ) 45 | 46 | if "%1" == "clean" ( 47 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 48 | del /q /s %BUILDDIR%\* 49 | goto end 50 | ) 51 | 52 | 53 | REM Check if sphinx-build is available and fallback to Python version if any 54 | %SPHINXBUILD% 1>NUL 2>NUL 55 | if errorlevel 9009 goto sphinx_python 56 | goto sphinx_ok 57 | 58 | :sphinx_python 59 | 60 | set SPHINXBUILD=python -m sphinx.__init__ 61 | %SPHINXBUILD% 2> nul 62 | if errorlevel 9009 ( 63 | echo. 64 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 65 | echo.installed, then set the SPHINXBUILD environment variable to point 66 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 67 | echo.may add the Sphinx directory to PATH. 68 | echo. 69 | echo.If you don't have Sphinx installed, grab it from 70 | echo.http://sphinx-doc.org/ 71 | exit /b 1 72 | ) 73 | 74 | :sphinx_ok 75 | 76 | 77 | if "%1" == "html" ( 78 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 79 | if errorlevel 1 exit /b 1 80 | echo. 81 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 82 | goto end 83 | ) 84 | 85 | if "%1" == "dirhtml" ( 86 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 87 | if errorlevel 1 exit /b 1 88 | echo. 89 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 90 | goto end 91 | ) 92 | 93 | if "%1" == "singlehtml" ( 94 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 95 | if errorlevel 1 exit /b 1 96 | echo. 97 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 98 | goto end 99 | ) 100 | 101 | if "%1" == "pickle" ( 102 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 103 | if errorlevel 1 exit /b 1 104 | echo. 105 | echo.Build finished; now you can process the pickle files. 106 | goto end 107 | ) 108 | 109 | if "%1" == "json" ( 110 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 111 | if errorlevel 1 exit /b 1 112 | echo. 113 | echo.Build finished; now you can process the JSON files. 114 | goto end 115 | ) 116 | 117 | if "%1" == "htmlhelp" ( 118 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 119 | if errorlevel 1 exit /b 1 120 | echo. 121 | echo.Build finished; now you can run HTML Help Workshop with the ^ 122 | .hhp project file in %BUILDDIR%/htmlhelp. 123 | goto end 124 | ) 125 | 126 | if "%1" == "qthelp" ( 127 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 128 | if errorlevel 1 exit /b 1 129 | echo. 130 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 131 | .qhcp project file in %BUILDDIR%/qthelp, like this: 132 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Shaolin.qhcp 133 | echo.To view the help file: 134 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Shaolin.ghc 135 | goto end 136 | ) 137 | 138 | if "%1" == "devhelp" ( 139 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 140 | if errorlevel 1 exit /b 1 141 | echo. 142 | echo.Build finished. 143 | goto end 144 | ) 145 | 146 | if "%1" == "epub" ( 147 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 148 | if errorlevel 1 exit /b 1 149 | echo. 150 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 151 | goto end 152 | ) 153 | 154 | if "%1" == "epub3" ( 155 | %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 156 | if errorlevel 1 exit /b 1 157 | echo. 158 | echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. 159 | goto end 160 | ) 161 | 162 | if "%1" == "latex" ( 163 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 164 | if errorlevel 1 exit /b 1 165 | echo. 166 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 167 | goto end 168 | ) 169 | 170 | if "%1" == "latexpdf" ( 171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 172 | cd %BUILDDIR%/latex 173 | make all-pdf 174 | cd %~dp0 175 | echo. 176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 177 | goto end 178 | ) 179 | 180 | if "%1" == "latexpdfja" ( 181 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 182 | cd %BUILDDIR%/latex 183 | make all-pdf-ja 184 | cd %~dp0 185 | echo. 186 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 187 | goto end 188 | ) 189 | 190 | if "%1" == "text" ( 191 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 192 | if errorlevel 1 exit /b 1 193 | echo. 194 | echo.Build finished. The text files are in %BUILDDIR%/text. 195 | goto end 196 | ) 197 | 198 | if "%1" == "man" ( 199 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 200 | if errorlevel 1 exit /b 1 201 | echo. 202 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 203 | goto end 204 | ) 205 | 206 | if "%1" == "texinfo" ( 207 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 208 | if errorlevel 1 exit /b 1 209 | echo. 210 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 211 | goto end 212 | ) 213 | 214 | if "%1" == "gettext" ( 215 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 216 | if errorlevel 1 exit /b 1 217 | echo. 218 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 219 | goto end 220 | ) 221 | 222 | if "%1" == "changes" ( 223 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 224 | if errorlevel 1 exit /b 1 225 | echo. 226 | echo.The overview file is in %BUILDDIR%/changes. 227 | goto end 228 | ) 229 | 230 | if "%1" == "linkcheck" ( 231 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 232 | if errorlevel 1 exit /b 1 233 | echo. 234 | echo.Link check complete; look for any errors in the above output ^ 235 | or in %BUILDDIR%/linkcheck/output.txt. 236 | goto end 237 | ) 238 | 239 | if "%1" == "doctest" ( 240 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 241 | if errorlevel 1 exit /b 1 242 | echo. 243 | echo.Testing of doctests in the sources finished, look at the ^ 244 | results in %BUILDDIR%/doctest/output.txt. 245 | goto end 246 | ) 247 | 248 | if "%1" == "coverage" ( 249 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 250 | if errorlevel 1 exit /b 1 251 | echo. 252 | echo.Testing of coverage in the sources finished, look at the ^ 253 | results in %BUILDDIR%/coverage/python.txt. 254 | goto end 255 | ) 256 | 257 | if "%1" == "xml" ( 258 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 259 | if errorlevel 1 exit /b 1 260 | echo. 261 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 262 | goto end 263 | ) 264 | 265 | if "%1" == "pseudoxml" ( 266 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 267 | if errorlevel 1 exit /b 1 268 | echo. 269 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 270 | goto end 271 | ) 272 | 273 | if "%1" == "dummy" ( 274 | %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy 275 | if errorlevel 1 exit /b 1 276 | echo. 277 | echo.Build finished. Dummy builder generates no files. 278 | goto end 279 | ) 280 | 281 | :end 282 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help 23 | help: 24 | @echo "Please use \`make ' where is one of" 25 | @echo " html to make standalone HTML files" 26 | @echo " dirhtml to make HTML files named index.html in directories" 27 | @echo " singlehtml to make a single large HTML file" 28 | @echo " pickle to make pickle files" 29 | @echo " json to make JSON files" 30 | @echo " htmlhelp to make HTML files and a HTML help project" 31 | @echo " qthelp to make HTML files and a qthelp project" 32 | @echo " applehelp to make an Apple Help Book" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " epub3 to make an epub3" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | @echo " dummy to check syntax errors of document sources" 51 | 52 | .PHONY: clean 53 | clean: 54 | rm -rf $(BUILDDIR)/* 55 | 56 | .PHONY: html 57 | html: 58 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 61 | 62 | .PHONY: dirhtml 63 | dirhtml: 64 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 65 | @echo 66 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 67 | 68 | .PHONY: singlehtml 69 | singlehtml: 70 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 71 | @echo 72 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 73 | 74 | .PHONY: pickle 75 | pickle: 76 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 77 | @echo 78 | @echo "Build finished; now you can process the pickle files." 79 | 80 | .PHONY: json 81 | json: 82 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 83 | @echo 84 | @echo "Build finished; now you can process the JSON files." 85 | 86 | .PHONY: htmlhelp 87 | htmlhelp: 88 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 89 | @echo 90 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 91 | ".hhp project file in $(BUILDDIR)/htmlhelp." 92 | 93 | .PHONY: qthelp 94 | qthelp: 95 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 96 | @echo 97 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 98 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 99 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Shaolin.qhcp" 100 | @echo "To view the help file:" 101 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Shaolin.qhc" 102 | 103 | .PHONY: applehelp 104 | applehelp: 105 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 106 | @echo 107 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 108 | @echo "N.B. You won't be able to view it unless you put it in" \ 109 | "~/Library/Documentation/Help or install it in your application" \ 110 | "bundle." 111 | 112 | .PHONY: devhelp 113 | devhelp: 114 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 115 | @echo 116 | @echo "Build finished." 117 | @echo "To view the help file:" 118 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Shaolin" 119 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Shaolin" 120 | @echo "# devhelp" 121 | 122 | .PHONY: epub 123 | epub: 124 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 125 | @echo 126 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 127 | 128 | .PHONY: epub3 129 | epub3: 130 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 131 | @echo 132 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." 133 | 134 | .PHONY: latex 135 | latex: 136 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 137 | @echo 138 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 139 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 140 | "(use \`make latexpdf' here to do that automatically)." 141 | 142 | .PHONY: latexpdf 143 | latexpdf: 144 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 145 | @echo "Running LaTeX files through pdflatex..." 146 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 147 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 148 | 149 | .PHONY: latexpdfja 150 | latexpdfja: 151 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 152 | @echo "Running LaTeX files through platex and dvipdfmx..." 153 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 154 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 155 | 156 | .PHONY: text 157 | text: 158 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 159 | @echo 160 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 161 | 162 | .PHONY: man 163 | man: 164 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 165 | @echo 166 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 167 | 168 | .PHONY: texinfo 169 | texinfo: 170 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 171 | @echo 172 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 173 | @echo "Run \`make' in that directory to run these through makeinfo" \ 174 | "(use \`make info' here to do that automatically)." 175 | 176 | .PHONY: info 177 | info: 178 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 179 | @echo "Running Texinfo files through makeinfo..." 180 | make -C $(BUILDDIR)/texinfo info 181 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 182 | 183 | .PHONY: gettext 184 | gettext: 185 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 186 | @echo 187 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 188 | 189 | .PHONY: changes 190 | changes: 191 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 192 | @echo 193 | @echo "The overview file is in $(BUILDDIR)/changes." 194 | 195 | .PHONY: linkcheck 196 | linkcheck: 197 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 198 | @echo 199 | @echo "Link check complete; look for any errors in the above output " \ 200 | "or in $(BUILDDIR)/linkcheck/output.txt." 201 | 202 | .PHONY: doctest 203 | doctest: 204 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 205 | @echo "Testing of doctests in the sources finished, look at the " \ 206 | "results in $(BUILDDIR)/doctest/output.txt." 207 | 208 | .PHONY: coverage 209 | coverage: 210 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 211 | @echo "Testing of coverage in the sources finished, look at the " \ 212 | "results in $(BUILDDIR)/coverage/python.txt." 213 | 214 | .PHONY: xml 215 | xml: 216 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 217 | @echo 218 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 219 | 220 | .PHONY: pseudoxml 221 | pseudoxml: 222 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 223 | @echo 224 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 225 | 226 | .PHONY: dummy 227 | dummy: 228 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy 229 | @echo 230 | @echo "Build finished. Dummy builder generates no files." 231 | -------------------------------------------------------------------------------- /shaolin/core/stateless_dashboard.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed May 25 15:26:23 2016 4 | 5 | @author: sergio 6 | """ 7 | import traitlets 8 | from shaolin import core as sc 9 | from shaolin.core import shaoscript as scpt 10 | class StatelessDashboard(object): 11 | """Clash for managing arbitrary Dashboards""" 12 | def __init__(self, dashboard, func=None, mode='active', name=None): 13 | 14 | self.func = func 15 | self.dashboard = dashboard 16 | self.mode = mode 17 | 18 | if not name is None: 19 | self.name = name 20 | elif hasattr(dashboard, 'name'): 21 | self.name = dashboard.name 22 | else: 23 | self.name = self.name_from_shaoscript(dashboard[0]) 24 | self.mode_dict = {'active' : [], 25 | 'passive': [], 26 | 'interactive' : [], 27 | 'all':[] 28 | } 29 | self._init_dash(self.dashboard) 30 | self._link_children(self.dashboard) 31 | if not self.func is None: 32 | self.observe(self.interact) 33 | #self.output = self.kwargs 34 | 35 | def _init_dashboard(self, dashboard): 36 | """Integrates a child Dashboard as an attribute of the current Dashboard""" 37 | setattr(self, dashboard.name, dashboard) 38 | if dashboard.mode == 'interactive': 39 | self.mode_dict['interactive'] += [dashboard.name] 40 | elif dashboard.mode == 'passive': 41 | self.mode_dict['passive'] += [dashboard.name] 42 | else: 43 | self.mode_dict['active'] += [dashboard.name] 44 | 45 | def _init_toggle_menu(self, children, kwargs): 46 | """Integrates a child ToggleMenu as an attribute of the current Dashboard""" 47 | dashboard = sc.dashboard.ToggleMenu(children) 48 | if 'name' in kwargs.keys(): 49 | dashboard.name = kwargs['name'] 50 | setattr(self, dashboard.name, dashboard) 51 | if dashboard.mode == 'interactive': 52 | self.mode_dict['interactive'] += [dashboard.name] 53 | elif dashboard.mode == 'passive': 54 | self.mode_dict['passive'] += [dashboard.name] 55 | else: 56 | self.mode_dict['active'] += [dashboard.name] 57 | 58 | def _init_widget(self, shao, kwargs): 59 | """Integrates a child Widget as an attribute of the current Dashboard""" 60 | 61 | 62 | widget = scpt.shaoscript(shao, kwargs) 63 | 64 | try: 65 | setattr(self, widget.name, widget) 66 | except Exception as e: 67 | e.args += (('Dont use widget attributes as shaoscript names,' 68 | 'they are reserved words! (You can use dashboard' 69 | 'as a generic name if you want)'),) 70 | raise e 71 | 72 | 73 | if widget.mode == 'interactive': 74 | self.mode_dict['interactive'] += [widget.name] 75 | elif widget.mode == 'passive': 76 | self.mode_dict['passive'] += [widget.name] 77 | else: 78 | self.mode_dict['active'] += [widget.name] 79 | 80 | self.mode_dict['all'] += [widget.name] 81 | 82 | def interact(self, _): 83 | """Apply the dashboard kwargs to the dashboard function""" 84 | self.func(self.output) 85 | 86 | def link(self, name_1, name_2): 87 | """Same as trailets but applied to Dashboard attribute names""" 88 | widget_1 = getattr(self, name_1).target 89 | widget_2 = getattr(self, name_2).target 90 | setattr(self, 'link_'+name_1+'_'+name_2, traitlets.link((widget_1, 'value'), 91 | (widget_2, 'value'))) 92 | 93 | def dlink(self, name_1, name_2): 94 | """Same as trailets but applied to Dashboard attribute names""" 95 | widget_1 = getattr(self, name_1).target 96 | widget_2 = getattr(self, name_2).target 97 | setattr(self, 'link_'+name_1+'_'+name_2, traitlets.dlink((widget_1, 'value'), 98 | (widget_2, 'value'))) 99 | 100 | def unlink(self, name_1, name_2): 101 | """Same as trailets but applied to Dashboard attribute names""" 102 | link = getattr(self, 'link_'+name_1+'_'+name_2) 103 | link.unlink() 104 | 105 | @property 106 | def visible(self): 107 | """Easy visibility management""" 108 | visible = False 109 | for name in self.mode_dict['all']: 110 | visible = visible or getattr(self, name).visible 111 | return visible 112 | @visible.setter 113 | def visible(self, val): 114 | """Easy visibility management""" 115 | for name in self.mode_dict['all']: 116 | getattr(self, name).visible = val 117 | 118 | @property 119 | def value(self): 120 | """alias for better modularity""" 121 | return self.kwargs 122 | 123 | @property 124 | def kwargs(self): 125 | """Children values as a kwargs dict for easier interactivity""" 126 | kwargs = {} 127 | for name in self.mode_dict['active']: 128 | kwargs[name] = getattr(self, name).value 129 | for name in self.mode_dict['interactive']: 130 | kwargs[name] = getattr(self, name).value 131 | return kwargs 132 | 133 | 134 | def set_kwargs(self, vals): 135 | """Children values as a kwargs dict for easier interactivity""" 136 | import shaolin.core.dashboard as sd 137 | for name in vals.keys(): 138 | attr = getattr(self, name) 139 | if isinstance(attr, sd.Dashboard): 140 | attr.set_kwargs(vals[name]) 141 | else: 142 | attr.value = vals[name] 143 | 144 | @property 145 | def interactive_kwargs(self): 146 | """Interactive children values as a kwargs dict for easier interactivity""" 147 | kw = {} 148 | for name in self.mode_dict['interactive']: 149 | kw[name] = getattr(self, name).value 150 | return kw 151 | @property 152 | def widget(self): 153 | """Alias for easy access to the Dashboard main widget""" 154 | return getattr(self, self.name_from_shaoscript(self.dashboard[0])).widget 155 | 156 | @staticmethod 157 | def name_from_shaoscript(string): 158 | """Get a name from a shaoscript string""" 159 | params = string.split('$')[1].split('&') 160 | desc = None 161 | name = None 162 | for p in params: 163 | pname = p.split('=')[0] 164 | if pname in ['d', 'desc', 'description', 'D']: 165 | desc = p.split('=')[1] 166 | elif pname in ['n', 'name', 'N']: 167 | name = p.split('=')[1] 168 | if name is None and desc is None: 169 | return False 170 | elif name is None: 171 | return desc.lower().replace(' ', '_') 172 | else: 173 | return name.lower().replace(' ', '_') 174 | 175 | @staticmethod 176 | def read_shaolist(shaolist): 177 | """Convert a shaolist block to a corresponding shaoscrpt, kwargs, 178 | children mapping""" 179 | #print("shaolist: {}".format(shaolist)) 180 | try: 181 | len(shaolist) 182 | except TypeError: 183 | shaoscrpt = None 184 | kwargs = {} 185 | children = None 186 | return shaoscrpt, kwargs, children 187 | 188 | if shaolist[0] is sc.dashboard.ToggleMenu: 189 | shaoscrpt = sc.dashboard.ToggleMenu 190 | kwargs = {} 191 | children = shaolist[1] 192 | elif isinstance(shaolist, str): 193 | shaoscrpt = shaolist 194 | kwargs = {} 195 | children = None 196 | elif len(shaolist) == 1: 197 | #[(shaoscript,kwargs)] 198 | if isinstance(shaolist[0], tuple): 199 | kwargs = shaolist[0][1] 200 | shaoscrpt = shaolist[0][0] 201 | children = None 202 | #[shaoscript] 203 | else: 204 | shaoscrpt = shaolist[0] 205 | kwargs = {} 206 | children = None 207 | elif len(shaolist) == 2: 208 | #[(shaoscript, kwargs), children] 209 | if isinstance(shaolist[0], tuple): 210 | if shaolist[0][0] is sc.dashboard.ToggleMenu: 211 | shaoscrpt = sc.dashboard.ToggleMenu 212 | kwargs = shaolist[0][1] 213 | children = shaolist[1] 214 | return shaoscrpt, kwargs, children 215 | else: 216 | kwargs = shaolist[0][1] 217 | shaoscrpt = shaolist[0][0] 218 | children = shaolist[1] 219 | #[shaoscript,children] 220 | else: 221 | kwargs = {} 222 | shaoscrpt = shaolist[0] 223 | children = shaolist[1] 224 | else: 225 | pass 226 | return shaoscrpt, kwargs, children 227 | 228 | def observe(self, func, names='value'): 229 | """Same as ipywidgets. Applies to all interactive children widgets""" 230 | for name in self.mode_dict['interactive']: 231 | getattr(self, name).observe(func, names=names) 232 | 233 | def _link_children(self, shaolist): 234 | """Creates the dashboard structure linking each children with its parent""" 235 | shaoscrpt, kwargs, children = self.read_shaolist(shaolist) 236 | if children is None: 237 | return 238 | else: 239 | name = self.name_from_shaoscript(shaoscrpt) 240 | for child in children: 241 | shao_c, kwargs_c, c_children = self.read_shaolist(child) 242 | if shao_c is None: 243 | cname = child.name 244 | else: 245 | cname = self.name_from_shaoscript(shao_c) 246 | getattr(self, name).target.children += (getattr(self, cname).widget,) 247 | self._link_children(child) 248 | 249 | def _init_dash(self, value): 250 | """Creates all the children Widgets and dashboards the current Dashboard will have""" 251 | shaoscrpt, kwargs, children = self.read_shaolist(value) 252 | if shaoscrpt is None: 253 | self._init_dashboard(value) 254 | elif shaoscrpt is sc.dashboard.ToggleMenu: 255 | self._init_toggle_menu(children, kwargs) 256 | else: 257 | self._init_widget(shaoscrpt, kwargs) 258 | if children is None: 259 | return 260 | for child in children: 261 | self._init_dash(child) 262 | 263 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Shaolin documentation build configuration file, created by 5 | # sphinx-quickstart on Sun May 8 20:56:25 2016. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import sys 17 | import os 18 | 19 | # If extensions (or modules to document with autodoc) are in another directory, 20 | # add these directories to sys.path here. If the directory is relative to the 21 | # documentation root, use os.path.abspath to make it absolute, like shown here. 22 | #sys.path.insert(0, os.path.abspath('.')) 23 | 24 | # -- General configuration ------------------------------------------------ 25 | 26 | # If your documentation needs a minimal Sphinx version, state it here. 27 | #needs_sphinx = '1.0' 28 | 29 | # Add any Sphinx extension module names here, as strings. They can be 30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 31 | # ones. 32 | extensions = [ 33 | 'sphinx.ext.autodoc', 34 | 'sphinx.ext.doctest', 35 | 'sphinx.ext.todo', 36 | 'sphinx.ext.coverage', 37 | 'sphinx.ext.mathjax', 38 | 'sphinx.ext.viewcode', 39 | ] 40 | 41 | # Add any paths that contain templates here, relative to this directory. 42 | templates_path = ['_templates'] 43 | 44 | # The suffix(es) of source filenames. 45 | # You can specify multiple suffix as a list of string: 46 | # source_suffix = ['.rst', '.md'] 47 | source_suffix = '.rst' 48 | 49 | # The encoding of source files. 50 | #source_encoding = 'utf-8-sig' 51 | 52 | # The master toctree document. 53 | master_doc = 'index' 54 | 55 | # General information about the project. 56 | project = 'Shaolin' 57 | copyright = '2016, Guillem Duran (HCSoft)' 58 | author = 'Guillem Duran (HCSoft)' 59 | 60 | # The version info for the project you're documenting, acts as replacement for 61 | # |version| and |release|, also used in various other places throughout the 62 | # built documents. 63 | # 64 | # The short X.Y version. 65 | version = '0.1' 66 | # The full version, including alpha/beta/rc tags. 67 | release = '0.0.1' 68 | 69 | # The language for content autogenerated by Sphinx. Refer to documentation 70 | # for a list of supported languages. 71 | # 72 | # This is also used if you do content translation via gettext catalogs. 73 | # Usually you set "language" from the command line for these cases. 74 | language = None 75 | 76 | # There are two options for replacing |today|: either, you set today to some 77 | # non-false value, then it is used: 78 | #today = '' 79 | # Else, today_fmt is used as the format for a strftime call. 80 | #today_fmt = '%B %d, %Y' 81 | 82 | # List of patterns, relative to source directory, that match files and 83 | # directories to ignore when looking for source files. 84 | # This patterns also effect to html_static_path and html_extra_path 85 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 86 | 87 | # The reST default role (used for this markup: `text`) to use for all 88 | # documents. 89 | #default_role = None 90 | 91 | # If true, '()' will be appended to :func: etc. cross-reference text. 92 | #add_function_parentheses = True 93 | 94 | # If true, the current module name will be prepended to all description 95 | # unit titles (such as .. function::). 96 | #add_module_names = True 97 | 98 | # If true, sectionauthor and moduleauthor directives will be shown in the 99 | # output. They are ignored by default. 100 | #show_authors = False 101 | 102 | # The name of the Pygments (syntax highlighting) style to use. 103 | pygments_style = 'sphinx' 104 | 105 | # A list of ignored prefixes for module index sorting. 106 | #modindex_common_prefix = [] 107 | 108 | # If true, keep warnings as "system message" paragraphs in the built documents. 109 | #keep_warnings = False 110 | 111 | # If true, `todo` and `todoList` produce output, else they produce nothing. 112 | todo_include_todos = True 113 | 114 | 115 | # -- Options for HTML output ---------------------------------------------- 116 | 117 | # The theme to use for HTML and HTML Help pages. See the documentation for 118 | # a list of builtin themes. 119 | html_theme = 'alabaster' 120 | 121 | # Theme options are theme-specific and customize the look and feel of a theme 122 | # further. For a list of options available for each theme, see the 123 | # documentation. 124 | #html_theme_options = {} 125 | 126 | # Add any paths that contain custom themes here, relative to this directory. 127 | #html_theme_path = [] 128 | 129 | # The name for this set of Sphinx documents. 130 | # " v documentation" by default. 131 | #html_title = 'Shaolin v0.0.1' 132 | 133 | # A shorter title for the navigation bar. Default is the same as html_title. 134 | #html_short_title = None 135 | 136 | # The name of an image file (relative to this directory) to place at the top 137 | # of the sidebar. 138 | #html_logo = None 139 | 140 | # The name of an image file (relative to this directory) to use as a favicon of 141 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 142 | # pixels large. 143 | #html_favicon = None 144 | 145 | # Add any paths that contain custom static files (such as style sheets) here, 146 | # relative to this directory. They are copied after the builtin static files, 147 | # so a file named "default.css" will overwrite the builtin "default.css". 148 | html_static_path = ['_static'] 149 | 150 | # Add any extra paths that contain custom files (such as robots.txt or 151 | # .htaccess) here, relative to this directory. These files are copied 152 | # directly to the root of the documentation. 153 | #html_extra_path = [] 154 | 155 | # If not None, a 'Last updated on:' timestamp is inserted at every page 156 | # bottom, using the given strftime format. 157 | # The empty string is equivalent to '%b %d, %Y'. 158 | #html_last_updated_fmt = None 159 | 160 | # If true, SmartyPants will be used to convert quotes and dashes to 161 | # typographically correct entities. 162 | #html_use_smartypants = True 163 | 164 | # Custom sidebar templates, maps document names to template names. 165 | #html_sidebars = {} 166 | 167 | # Additional templates that should be rendered to pages, maps page names to 168 | # template names. 169 | #html_additional_pages = {} 170 | 171 | # If false, no module index is generated. 172 | #html_domain_indices = True 173 | 174 | # If false, no index is generated. 175 | #html_use_index = True 176 | 177 | # If true, the index is split into individual pages for each letter. 178 | #html_split_index = False 179 | 180 | # If true, links to the reST sources are added to the pages. 181 | #html_show_sourcelink = True 182 | 183 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 184 | #html_show_sphinx = True 185 | 186 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 187 | #html_show_copyright = True 188 | 189 | # If true, an OpenSearch description file will be output, and all pages will 190 | # contain a tag referring to it. The value of this option must be the 191 | # base URL from which the finished HTML is served. 192 | #html_use_opensearch = '' 193 | 194 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 195 | #html_file_suffix = None 196 | 197 | # Language to be used for generating the HTML full-text search index. 198 | # Sphinx supports the following languages: 199 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 200 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh' 201 | #html_search_language = 'en' 202 | 203 | # A dictionary with options for the search language support, empty by default. 204 | # 'ja' uses this config value. 205 | # 'zh' user can custom change `jieba` dictionary path. 206 | #html_search_options = {'type': 'default'} 207 | 208 | # The name of a javascript file (relative to the configuration directory) that 209 | # implements a search results scorer. If empty, the default will be used. 210 | #html_search_scorer = 'scorer.js' 211 | 212 | # Output file base name for HTML help builder. 213 | htmlhelp_basename = 'Shaolindoc' 214 | 215 | # -- Options for LaTeX output --------------------------------------------- 216 | 217 | latex_elements = { 218 | # The paper size ('letterpaper' or 'a4paper'). 219 | #'papersize': 'letterpaper', 220 | 221 | # The font size ('10pt', '11pt' or '12pt'). 222 | #'pointsize': '10pt', 223 | 224 | # Additional stuff for the LaTeX preamble. 225 | #'preamble': '', 226 | 227 | # Latex figure (float) alignment 228 | #'figure_align': 'htbp', 229 | } 230 | 231 | # Grouping the document tree into LaTeX files. List of tuples 232 | # (source start file, target name, title, 233 | # author, documentclass [howto, manual, or own class]). 234 | latex_documents = [ 235 | (master_doc, 'Shaolin.tex', 'Shaolin Documentation', 236 | 'Guillem Duran (HCSoft)', 'manual'), 237 | ] 238 | 239 | # The name of an image file (relative to this directory) to place at the top of 240 | # the title page. 241 | #latex_logo = None 242 | 243 | # For "manual" documents, if this is true, then toplevel headings are parts, 244 | # not chapters. 245 | #latex_use_parts = False 246 | 247 | # If true, show page references after internal links. 248 | #latex_show_pagerefs = False 249 | 250 | # If true, show URL addresses after external links. 251 | #latex_show_urls = False 252 | 253 | # Documents to append as an appendix to all manuals. 254 | #latex_appendices = [] 255 | 256 | # If false, no module index is generated. 257 | #latex_domain_indices = True 258 | 259 | 260 | # -- Options for manual page output --------------------------------------- 261 | 262 | # One entry per manual page. List of tuples 263 | # (source start file, name, description, authors, manual section). 264 | man_pages = [ 265 | (master_doc, 'shaolin', 'Shaolin Documentation', 266 | [author], 1) 267 | ] 268 | 269 | # If true, show URL addresses after external links. 270 | #man_show_urls = False 271 | 272 | 273 | # -- Options for Texinfo output ------------------------------------------- 274 | 275 | # Grouping the document tree into Texinfo files. List of tuples 276 | # (source start file, target name, title, author, 277 | # dir menu entry, description, category) 278 | texinfo_documents = [ 279 | (master_doc, 'Shaolin', 'Shaolin Documentation', 280 | author, 'Shaolin', 'One line description of project.', 281 | 'Miscellaneous'), 282 | ] 283 | 284 | # Documents to append as an appendix to all manuals. 285 | #texinfo_appendices = [] 286 | 287 | # If false, no module index is generated. 288 | #texinfo_domain_indices = True 289 | 290 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 291 | #texinfo_show_urls = 'footnote' 292 | 293 | # If true, do not generate a @detailmenu in the "Top" node's menu. 294 | #texinfo_no_detailmenu = False 295 | -------------------------------------------------------------------------------- /docs/_build/html/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/_build/html/_static/alabaster.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | @import url("basic.css"); 19 | 20 | /* -- page layout ----------------------------------------------------------- */ 21 | 22 | body { 23 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; 24 | font-size: 17px; 25 | background-color: white; 26 | color: #000; 27 | margin: 0; 28 | padding: 0; 29 | } 30 | 31 | 32 | div.document { 33 | width: 940px; 34 | margin: 30px auto 0 auto; 35 | } 36 | 37 | div.documentwrapper { 38 | float: left; 39 | width: 100%; 40 | } 41 | 42 | div.bodywrapper { 43 | margin: 0 0 0 220px; 44 | } 45 | 46 | div.sphinxsidebar { 47 | width: 220px; 48 | font-size: 14px; 49 | line-height: 1.5; 50 | } 51 | 52 | hr { 53 | border: 1px solid #B1B4B6; 54 | } 55 | 56 | div.body { 57 | background-color: #ffffff; 58 | color: #3E4349; 59 | padding: 0 30px 0 30px; 60 | } 61 | 62 | div.body > .section { 63 | text-align: left; 64 | } 65 | 66 | div.footer { 67 | width: 940px; 68 | margin: 20px auto 30px auto; 69 | font-size: 14px; 70 | color: #888; 71 | text-align: right; 72 | } 73 | 74 | div.footer a { 75 | color: #888; 76 | } 77 | 78 | p.caption { 79 | font-family: ; 80 | font-size: inherit; 81 | } 82 | 83 | 84 | div.relations { 85 | display: none; 86 | } 87 | 88 | 89 | div.sphinxsidebar a { 90 | color: #444; 91 | text-decoration: none; 92 | border-bottom: 1px dotted #999; 93 | } 94 | 95 | div.sphinxsidebar a:hover { 96 | border-bottom: 1px solid #999; 97 | } 98 | 99 | div.sphinxsidebarwrapper { 100 | padding: 18px 10px; 101 | } 102 | 103 | div.sphinxsidebarwrapper p.logo { 104 | padding: 0; 105 | margin: -10px 0 0 0px; 106 | text-align: center; 107 | } 108 | 109 | div.sphinxsidebarwrapper h1.logo { 110 | margin-top: -10px; 111 | text-align: center; 112 | margin-bottom: 5px; 113 | text-align: left; 114 | } 115 | 116 | div.sphinxsidebarwrapper h1.logo-name { 117 | margin-top: 0px; 118 | } 119 | 120 | div.sphinxsidebarwrapper p.blurb { 121 | margin-top: 0; 122 | font-style: normal; 123 | } 124 | 125 | div.sphinxsidebar h3, 126 | div.sphinxsidebar h4 { 127 | font-family: 'Garamond', 'Georgia', serif; 128 | color: #444; 129 | font-size: 24px; 130 | font-weight: normal; 131 | margin: 0 0 5px 0; 132 | padding: 0; 133 | } 134 | 135 | div.sphinxsidebar h4 { 136 | font-size: 20px; 137 | } 138 | 139 | div.sphinxsidebar h3 a { 140 | color: #444; 141 | } 142 | 143 | div.sphinxsidebar p.logo a, 144 | div.sphinxsidebar h3 a, 145 | div.sphinxsidebar p.logo a:hover, 146 | div.sphinxsidebar h3 a:hover { 147 | border: none; 148 | } 149 | 150 | div.sphinxsidebar p { 151 | color: #555; 152 | margin: 10px 0; 153 | } 154 | 155 | div.sphinxsidebar ul { 156 | margin: 10px 0; 157 | padding: 0; 158 | color: #000; 159 | } 160 | 161 | div.sphinxsidebar ul li.toctree-l1 > a { 162 | font-size: 120%; 163 | } 164 | 165 | div.sphinxsidebar ul li.toctree-l2 > a { 166 | font-size: 110%; 167 | } 168 | 169 | div.sphinxsidebar input { 170 | border: 1px solid #CCC; 171 | font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; 172 | font-size: 1em; 173 | } 174 | 175 | div.sphinxsidebar hr { 176 | border: none; 177 | height: 1px; 178 | color: #AAA; 179 | background: #AAA; 180 | 181 | text-align: left; 182 | margin-left: 0; 183 | width: 50%; 184 | } 185 | 186 | /* -- body styles ----------------------------------------------------------- */ 187 | 188 | a { 189 | color: #004B6B; 190 | text-decoration: underline; 191 | } 192 | 193 | a:hover { 194 | color: #6D4100; 195 | text-decoration: underline; 196 | } 197 | 198 | div.body h1, 199 | div.body h2, 200 | div.body h3, 201 | div.body h4, 202 | div.body h5, 203 | div.body h6 { 204 | font-family: 'Garamond', 'Georgia', serif; 205 | font-weight: normal; 206 | margin: 30px 0px 10px 0px; 207 | padding: 0; 208 | } 209 | 210 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } 211 | div.body h2 { font-size: 180%; } 212 | div.body h3 { font-size: 150%; } 213 | div.body h4 { font-size: 130%; } 214 | div.body h5 { font-size: 100%; } 215 | div.body h6 { font-size: 100%; } 216 | 217 | a.headerlink { 218 | color: #DDD; 219 | padding: 0 4px; 220 | text-decoration: none; 221 | } 222 | 223 | a.headerlink:hover { 224 | color: #444; 225 | background: #EAEAEA; 226 | } 227 | 228 | div.body p, div.body dd, div.body li { 229 | line-height: 1.4em; 230 | } 231 | 232 | div.admonition { 233 | margin: 20px 0px; 234 | padding: 10px 30px; 235 | background-color: #FCC; 236 | border: 1px solid #FAA; 237 | } 238 | 239 | div.admonition tt.xref, div.admonition a tt { 240 | border-bottom: 1px solid #fafafa; 241 | } 242 | 243 | dd div.admonition { 244 | margin-left: -60px; 245 | padding-left: 60px; 246 | } 247 | 248 | div.admonition p.admonition-title { 249 | font-family: 'Garamond', 'Georgia', serif; 250 | font-weight: normal; 251 | font-size: 24px; 252 | margin: 0 0 10px 0; 253 | padding: 0; 254 | line-height: 1; 255 | } 256 | 257 | div.admonition p.last { 258 | margin-bottom: 0; 259 | } 260 | 261 | div.highlight { 262 | background-color: white; 263 | } 264 | 265 | dt:target, .highlight { 266 | background: #FAF3E8; 267 | } 268 | 269 | div.note { 270 | background-color: #EEE; 271 | border: 1px solid #CCC; 272 | } 273 | 274 | div.seealso { 275 | background-color: #EEE; 276 | border: 1px solid #CCC; 277 | } 278 | 279 | div.topic { 280 | background-color: #eee; 281 | } 282 | 283 | p.admonition-title { 284 | display: inline; 285 | } 286 | 287 | p.admonition-title:after { 288 | content: ":"; 289 | } 290 | 291 | pre, tt, code { 292 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 293 | font-size: 0.9em; 294 | } 295 | 296 | .hll { 297 | background-color: #FFC; 298 | margin: 0 -12px; 299 | padding: 0 12px; 300 | display: block; 301 | } 302 | 303 | img.screenshot { 304 | } 305 | 306 | tt.descname, tt.descclassname, code.descname, code.descclassname { 307 | font-size: 0.95em; 308 | } 309 | 310 | tt.descname, code.descname { 311 | padding-right: 0.08em; 312 | } 313 | 314 | img.screenshot { 315 | -moz-box-shadow: 2px 2px 4px #eee; 316 | -webkit-box-shadow: 2px 2px 4px #eee; 317 | box-shadow: 2px 2px 4px #eee; 318 | } 319 | 320 | table.docutils { 321 | border: 1px solid #888; 322 | -moz-box-shadow: 2px 2px 4px #eee; 323 | -webkit-box-shadow: 2px 2px 4px #eee; 324 | box-shadow: 2px 2px 4px #eee; 325 | } 326 | 327 | table.docutils td, table.docutils th { 328 | border: 1px solid #888; 329 | padding: 0.25em 0.7em; 330 | } 331 | 332 | table.field-list, table.footnote { 333 | border: none; 334 | -moz-box-shadow: none; 335 | -webkit-box-shadow: none; 336 | box-shadow: none; 337 | } 338 | 339 | table.footnote { 340 | margin: 15px 0; 341 | width: 100%; 342 | border: 1px solid #EEE; 343 | background: #FDFDFD; 344 | font-size: 0.9em; 345 | } 346 | 347 | table.footnote + table.footnote { 348 | margin-top: -15px; 349 | border-top: none; 350 | } 351 | 352 | table.field-list th { 353 | padding: 0 0.8em 0 0; 354 | } 355 | 356 | table.field-list td { 357 | padding: 0; 358 | } 359 | 360 | table.field-list p { 361 | margin-bottom: 0.8em; 362 | } 363 | 364 | table.footnote td.label { 365 | width: .1px; 366 | padding: 0.3em 0 0.3em 0.5em; 367 | } 368 | 369 | table.footnote td { 370 | padding: 0.3em 0.5em; 371 | } 372 | 373 | dl { 374 | margin: 0; 375 | padding: 0; 376 | } 377 | 378 | dl dd { 379 | margin-left: 30px; 380 | } 381 | 382 | blockquote { 383 | margin: 0 0 0 30px; 384 | padding: 0; 385 | } 386 | 387 | ul, ol { 388 | /* Matches the 30px from the narrow-screen "li > ul" selector below */ 389 | margin: 10px 0 10px 30px; 390 | padding: 0; 391 | } 392 | 393 | pre { 394 | background: #EEE; 395 | padding: 7px 30px; 396 | margin: 15px 0px; 397 | line-height: 1.3em; 398 | } 399 | 400 | dl pre, blockquote pre, li pre { 401 | margin-left: 0; 402 | padding-left: 30px; 403 | } 404 | 405 | dl dl pre { 406 | margin-left: -90px; 407 | padding-left: 90px; 408 | } 409 | 410 | tt, code { 411 | background-color: #ecf0f3; 412 | color: #222; 413 | /* padding: 1px 2px; */ 414 | } 415 | 416 | tt.xref, code.xref, a tt { 417 | background-color: #FBFBFB; 418 | border-bottom: 1px solid white; 419 | } 420 | 421 | a.reference { 422 | text-decoration: none; 423 | border-bottom: 1px dotted #004B6B; 424 | } 425 | 426 | /* Don't put an underline on images */ 427 | a.image-reference, a.image-reference:hover { 428 | border-bottom: none; 429 | } 430 | 431 | a.reference:hover { 432 | border-bottom: 1px solid #6D4100; 433 | } 434 | 435 | a.footnote-reference { 436 | text-decoration: none; 437 | font-size: 0.7em; 438 | vertical-align: top; 439 | border-bottom: 1px dotted #004B6B; 440 | } 441 | 442 | a.footnote-reference:hover { 443 | border-bottom: 1px solid #6D4100; 444 | } 445 | 446 | a:hover tt, a:hover code { 447 | background: #EEE; 448 | } 449 | 450 | 451 | @media screen and (max-width: 870px) { 452 | 453 | div.sphinxsidebar { 454 | display: none; 455 | } 456 | 457 | div.document { 458 | width: 100%; 459 | 460 | } 461 | 462 | div.documentwrapper { 463 | margin-left: 0; 464 | margin-top: 0; 465 | margin-right: 0; 466 | margin-bottom: 0; 467 | } 468 | 469 | div.bodywrapper { 470 | margin-top: 0; 471 | margin-right: 0; 472 | margin-bottom: 0; 473 | margin-left: 0; 474 | } 475 | 476 | ul { 477 | margin-left: 0; 478 | } 479 | 480 | li > ul { 481 | /* Matches the 30px from the "ul, ol" selector above */ 482 | margin-left: 30px; 483 | } 484 | 485 | .document { 486 | width: auto; 487 | } 488 | 489 | .footer { 490 | width: auto; 491 | } 492 | 493 | .bodywrapper { 494 | margin: 0; 495 | } 496 | 497 | .footer { 498 | width: auto; 499 | } 500 | 501 | .github { 502 | display: none; 503 | } 504 | 505 | 506 | 507 | } 508 | 509 | 510 | 511 | @media screen and (max-width: 875px) { 512 | 513 | body { 514 | margin: 0; 515 | padding: 20px 30px; 516 | } 517 | 518 | div.documentwrapper { 519 | float: none; 520 | background: white; 521 | } 522 | 523 | div.sphinxsidebar { 524 | display: block; 525 | float: none; 526 | width: 102.5%; 527 | margin: 50px -30px -20px -30px; 528 | padding: 10px 20px; 529 | background: #333; 530 | color: #FFF; 531 | } 532 | 533 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 534 | div.sphinxsidebar h3 a { 535 | color: white; 536 | } 537 | 538 | div.sphinxsidebar a { 539 | color: #AAA; 540 | } 541 | 542 | div.sphinxsidebar p.logo { 543 | display: none; 544 | } 545 | 546 | div.document { 547 | width: 100%; 548 | margin: 0; 549 | } 550 | 551 | div.footer { 552 | display: none; 553 | } 554 | 555 | div.bodywrapper { 556 | margin: 0; 557 | } 558 | 559 | div.body { 560 | min-height: 0; 561 | padding: 0; 562 | } 563 | 564 | .rtd_doc_footer { 565 | display: none; 566 | } 567 | 568 | .document { 569 | width: auto; 570 | } 571 | 572 | .footer { 573 | width: auto; 574 | } 575 | 576 | .footer { 577 | width: auto; 578 | } 579 | 580 | .github { 581 | display: none; 582 | } 583 | } 584 | 585 | 586 | /* misc. */ 587 | 588 | .revsys-inline { 589 | display: none!important; 590 | } 591 | 592 | /* Make nested-list/multi-paragraph items look better in Releases changelog 593 | * pages. Without this, docutils' magical list fuckery causes inconsistent 594 | * formatting between different release sub-lists. 595 | */ 596 | div#changelog > div.section > ul > li > p:only-child { 597 | margin-bottom: 0; 598 | } 599 | 600 | /* Hide fugly table cell borders in ..bibliography:: directive output */ 601 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th { 602 | border: none; 603 | /* Below needed in some edge cases; if not applied, bottom shadows appear */ 604 | -moz-box-shadow: none; 605 | -webkit-box-shadow: none; 606 | box-shadow: none; 607 | } -------------------------------------------------------------------------------- /docs/_build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox input[type="text"] { 85 | width: 170px; 86 | } 87 | 88 | div.sphinxsidebar #searchbox input[type="submit"] { 89 | width: 30px; 90 | } 91 | 92 | img { 93 | border: 0; 94 | max-width: 100%; 95 | } 96 | 97 | /* -- search page ----------------------------------------------------------- */ 98 | 99 | ul.search { 100 | margin: 10px 0 0 20px; 101 | padding: 0; 102 | } 103 | 104 | ul.search li { 105 | padding: 5px 0 5px 20px; 106 | background-image: url(file.png); 107 | background-repeat: no-repeat; 108 | background-position: 0 7px; 109 | } 110 | 111 | ul.search li a { 112 | font-weight: bold; 113 | } 114 | 115 | ul.search li div.context { 116 | color: #888; 117 | margin: 2px 0 0 30px; 118 | text-align: left; 119 | } 120 | 121 | ul.keywordmatches li.goodmatch a { 122 | font-weight: bold; 123 | } 124 | 125 | /* -- index page ------------------------------------------------------------ */ 126 | 127 | table.contentstable { 128 | width: 90%; 129 | } 130 | 131 | table.contentstable p.biglink { 132 | line-height: 150%; 133 | } 134 | 135 | a.biglink { 136 | font-size: 1.3em; 137 | } 138 | 139 | span.linkdescr { 140 | font-style: italic; 141 | padding-top: 5px; 142 | font-size: 90%; 143 | } 144 | 145 | /* -- general index --------------------------------------------------------- */ 146 | 147 | table.indextable { 148 | width: 100%; 149 | } 150 | 151 | table.indextable td { 152 | text-align: left; 153 | vertical-align: top; 154 | } 155 | 156 | table.indextable dl, table.indextable dd { 157 | margin-top: 0; 158 | margin-bottom: 0; 159 | } 160 | 161 | table.indextable tr.pcap { 162 | height: 10px; 163 | } 164 | 165 | table.indextable tr.cap { 166 | margin-top: 10px; 167 | background-color: #f2f2f2; 168 | } 169 | 170 | img.toggler { 171 | margin-right: 3px; 172 | margin-top: 3px; 173 | cursor: pointer; 174 | } 175 | 176 | div.modindex-jumpbox { 177 | border-top: 1px solid #ddd; 178 | border-bottom: 1px solid #ddd; 179 | margin: 1em 0 1em 0; 180 | padding: 0.4em; 181 | } 182 | 183 | div.genindex-jumpbox { 184 | border-top: 1px solid #ddd; 185 | border-bottom: 1px solid #ddd; 186 | margin: 1em 0 1em 0; 187 | padding: 0.4em; 188 | } 189 | 190 | /* -- general body styles --------------------------------------------------- */ 191 | 192 | div.body p, div.body dd, div.body li, div.body blockquote { 193 | -moz-hyphens: auto; 194 | -ms-hyphens: auto; 195 | -webkit-hyphens: auto; 196 | hyphens: auto; 197 | } 198 | 199 | a.headerlink { 200 | visibility: hidden; 201 | } 202 | 203 | h1:hover > a.headerlink, 204 | h2:hover > a.headerlink, 205 | h3:hover > a.headerlink, 206 | h4:hover > a.headerlink, 207 | h5:hover > a.headerlink, 208 | h6:hover > a.headerlink, 209 | dt:hover > a.headerlink, 210 | caption:hover > a.headerlink, 211 | p.caption:hover > a.headerlink, 212 | div.code-block-caption:hover > a.headerlink { 213 | visibility: visible; 214 | } 215 | 216 | div.body p.caption { 217 | text-align: inherit; 218 | } 219 | 220 | div.body td { 221 | text-align: left; 222 | } 223 | 224 | .field-list ul { 225 | padding-left: 1em; 226 | } 227 | 228 | .first { 229 | margin-top: 0 !important; 230 | } 231 | 232 | p.rubric { 233 | margin-top: 30px; 234 | font-weight: bold; 235 | } 236 | 237 | img.align-left, .figure.align-left, object.align-left { 238 | clear: left; 239 | float: left; 240 | margin-right: 1em; 241 | } 242 | 243 | img.align-right, .figure.align-right, object.align-right { 244 | clear: right; 245 | float: right; 246 | margin-left: 1em; 247 | } 248 | 249 | img.align-center, .figure.align-center, object.align-center { 250 | display: block; 251 | margin-left: auto; 252 | margin-right: auto; 253 | } 254 | 255 | .align-left { 256 | text-align: left; 257 | } 258 | 259 | .align-center { 260 | text-align: center; 261 | } 262 | 263 | .align-right { 264 | text-align: right; 265 | } 266 | 267 | /* -- sidebars -------------------------------------------------------------- */ 268 | 269 | div.sidebar { 270 | margin: 0 0 0.5em 1em; 271 | border: 1px solid #ddb; 272 | padding: 7px 7px 0 7px; 273 | background-color: #ffe; 274 | width: 40%; 275 | float: right; 276 | } 277 | 278 | p.sidebar-title { 279 | font-weight: bold; 280 | } 281 | 282 | /* -- topics ---------------------------------------------------------------- */ 283 | 284 | div.topic { 285 | border: 1px solid #ccc; 286 | padding: 7px 7px 0 7px; 287 | margin: 10px 0 10px 0; 288 | } 289 | 290 | p.topic-title { 291 | font-size: 1.1em; 292 | font-weight: bold; 293 | margin-top: 10px; 294 | } 295 | 296 | /* -- admonitions ----------------------------------------------------------- */ 297 | 298 | div.admonition { 299 | margin-top: 10px; 300 | margin-bottom: 10px; 301 | padding: 7px; 302 | } 303 | 304 | div.admonition dt { 305 | font-weight: bold; 306 | } 307 | 308 | div.admonition dl { 309 | margin-bottom: 0; 310 | } 311 | 312 | p.admonition-title { 313 | margin: 0px 10px 5px 0px; 314 | font-weight: bold; 315 | } 316 | 317 | div.body p.centered { 318 | text-align: center; 319 | margin-top: 25px; 320 | } 321 | 322 | /* -- tables ---------------------------------------------------------------- */ 323 | 324 | table.docutils { 325 | border: 0; 326 | border-collapse: collapse; 327 | } 328 | 329 | table caption span.caption-number { 330 | font-style: italic; 331 | } 332 | 333 | table caption span.caption-text { 334 | } 335 | 336 | table.docutils td, table.docutils th { 337 | padding: 1px 8px 1px 5px; 338 | border-top: 0; 339 | border-left: 0; 340 | border-right: 0; 341 | border-bottom: 1px solid #aaa; 342 | } 343 | 344 | table.field-list td, table.field-list th { 345 | border: 0 !important; 346 | } 347 | 348 | table.footnote td, table.footnote th { 349 | border: 0 !important; 350 | } 351 | 352 | th { 353 | text-align: left; 354 | padding-right: 5px; 355 | } 356 | 357 | table.citation { 358 | border-left: solid 1px gray; 359 | margin-left: 1px; 360 | } 361 | 362 | table.citation td { 363 | border-bottom: none; 364 | } 365 | 366 | /* -- figures --------------------------------------------------------------- */ 367 | 368 | div.figure { 369 | margin: 0.5em; 370 | padding: 0.5em; 371 | } 372 | 373 | div.figure p.caption { 374 | padding: 0.3em; 375 | } 376 | 377 | div.figure p.caption span.caption-number { 378 | font-style: italic; 379 | } 380 | 381 | div.figure p.caption span.caption-text { 382 | } 383 | 384 | 385 | /* -- other body styles ----------------------------------------------------- */ 386 | 387 | ol.arabic { 388 | list-style: decimal; 389 | } 390 | 391 | ol.loweralpha { 392 | list-style: lower-alpha; 393 | } 394 | 395 | ol.upperalpha { 396 | list-style: upper-alpha; 397 | } 398 | 399 | ol.lowerroman { 400 | list-style: lower-roman; 401 | } 402 | 403 | ol.upperroman { 404 | list-style: upper-roman; 405 | } 406 | 407 | dl { 408 | margin-bottom: 15px; 409 | } 410 | 411 | dd p { 412 | margin-top: 0px; 413 | } 414 | 415 | dd ul, dd table { 416 | margin-bottom: 10px; 417 | } 418 | 419 | dd { 420 | margin-top: 3px; 421 | margin-bottom: 10px; 422 | margin-left: 30px; 423 | } 424 | 425 | dt:target, .highlighted { 426 | background-color: #fbe54e; 427 | } 428 | 429 | dl.glossary dt { 430 | font-weight: bold; 431 | font-size: 1.1em; 432 | } 433 | 434 | .field-list ul { 435 | margin: 0; 436 | padding-left: 1em; 437 | } 438 | 439 | .field-list p { 440 | margin: 0; 441 | } 442 | 443 | .optional { 444 | font-size: 1.3em; 445 | } 446 | 447 | .sig-paren { 448 | font-size: larger; 449 | } 450 | 451 | .versionmodified { 452 | font-style: italic; 453 | } 454 | 455 | .system-message { 456 | background-color: #fda; 457 | padding: 5px; 458 | border: 3px solid red; 459 | } 460 | 461 | .footnote:target { 462 | background-color: #ffa; 463 | } 464 | 465 | .line-block { 466 | display: block; 467 | margin-top: 1em; 468 | margin-bottom: 1em; 469 | } 470 | 471 | .line-block .line-block { 472 | margin-top: 0; 473 | margin-bottom: 0; 474 | margin-left: 1.5em; 475 | } 476 | 477 | .guilabel, .menuselection { 478 | font-family: sans-serif; 479 | } 480 | 481 | .accelerator { 482 | text-decoration: underline; 483 | } 484 | 485 | .classifier { 486 | font-style: oblique; 487 | } 488 | 489 | abbr, acronym { 490 | border-bottom: dotted 1px; 491 | cursor: help; 492 | } 493 | 494 | /* -- code displays --------------------------------------------------------- */ 495 | 496 | pre { 497 | overflow: auto; 498 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 499 | } 500 | 501 | td.linenos pre { 502 | padding: 5px 0px; 503 | border: 0; 504 | background-color: transparent; 505 | color: #aaa; 506 | } 507 | 508 | table.highlighttable { 509 | margin-left: 0.5em; 510 | } 511 | 512 | table.highlighttable td { 513 | padding: 0 0.5em 0 0.5em; 514 | } 515 | 516 | div.code-block-caption { 517 | padding: 2px 5px; 518 | font-size: small; 519 | } 520 | 521 | div.code-block-caption code { 522 | background-color: transparent; 523 | } 524 | 525 | div.code-block-caption + div > div.highlight > pre { 526 | margin-top: 0; 527 | } 528 | 529 | div.code-block-caption span.caption-number { 530 | padding: 0.1em 0.3em; 531 | font-style: italic; 532 | } 533 | 534 | div.code-block-caption span.caption-text { 535 | } 536 | 537 | div.literal-block-wrapper { 538 | padding: 1em 1em 0; 539 | } 540 | 541 | div.literal-block-wrapper div.highlight { 542 | margin: 0; 543 | } 544 | 545 | code.descname { 546 | background-color: transparent; 547 | font-weight: bold; 548 | font-size: 1.2em; 549 | } 550 | 551 | code.descclassname { 552 | background-color: transparent; 553 | } 554 | 555 | code.xref, a code { 556 | background-color: transparent; 557 | font-weight: bold; 558 | } 559 | 560 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 561 | background-color: transparent; 562 | } 563 | 564 | .viewcode-link { 565 | float: right; 566 | } 567 | 568 | .viewcode-back { 569 | float: right; 570 | font-family: sans-serif; 571 | } 572 | 573 | div.viewcode-block:target { 574 | margin: -1px -10px; 575 | padding: 0 10px; 576 | } 577 | 578 | /* -- math display ---------------------------------------------------------- */ 579 | 580 | img.math { 581 | vertical-align: middle; 582 | } 583 | 584 | div.body div.math p { 585 | text-align: center; 586 | } 587 | 588 | span.eqno { 589 | float: right; 590 | } 591 | 592 | /* -- printout stylesheet --------------------------------------------------- */ 593 | 594 | @media print { 595 | div.document, 596 | div.documentwrapper, 597 | div.bodywrapper { 598 | margin: 0 !important; 599 | width: 100%; 600 | } 601 | 602 | div.sphinxsidebar, 603 | div.related, 604 | div.footer, 605 | #top-link { 606 | display: none; 607 | } 608 | } -------------------------------------------------------------------------------- /shaolin/core/widgets.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | Created on Wed Apr 20 10:22:21 2016 4 | 5 | @author: Guillem Duran for HCSOFT 6 | """ 7 | 8 | import ipywidgets as wid 9 | 10 | class Widget(object): 11 | """This is a wrapper for any selector widget so its description can be tweaked with css 12 | Parameters. This will also make backwadrs compatible the instantiation with layout properties. 13 | ---------- 14 | widget : ipydidgets widget 15 | this is intender for selector widgets, but it can be 16 | any widget with from the ipywidgets package. 17 | description : String or None 18 | Text for the description of the widget. Acs as the description 19 | parameter of the widget but can be tweaked with css 20 | desc_css : String or None 21 | css for the description text. 22 | custom_id : String or None 23 | A custom attribute tag for the description div. 24 | kwargs : **kwargs 25 | Arguments of the widget we are wrapping. 26 | """ 27 | def __init__(self, 28 | widget, 29 | class_=None, 30 | id=None, 31 | name=None, 32 | html=None, 33 | js=None, 34 | css=None, 35 | visible=True, 36 | mode='active', 37 | **kwargs): 38 | 39 | if id is None: 40 | id = '' 41 | else: 42 | id = id.lower().replace(' ', '_') 43 | if html is None: 44 | html = '' 45 | if js is None: 46 | js = '' 47 | if css is None: 48 | css = '' 49 | if name is None: 50 | name = '' 51 | else: 52 | name = name.lower().replace(' ', '_') 53 | if class_ is None: 54 | class_ = '' 55 | self.mode = mode 56 | self.name = name 57 | self.id = id 58 | self.class_ = class_ 59 | self.html = html 60 | self.js = js 61 | self.css = css 62 | """ 63 | #this ensures a unique class name for javascript hacking 64 | self._hack_id = ''.join(random.choice('0123456789ABCDEFGHIJK') for i in range(16)) 65 | self._hack_widget = wid.HTML(value='
'\ 66 | +''\ 67 | +''+self.html) 68 | self._hack_widget.layout.display = 'none' 69 | self._hack_widget.layout.visibility = 'hidden' 70 | 71 | self._label_css = '' 72 | #if 'description' in kwargs.keys(): 73 | # self.description = kwargs['description'] 74 | # kwargs.pop('description') 75 | 76 | self._description = description 77 | self.label = wid.HTML(value='
'+self._description+'
') 79 | if self._description == '': 80 | self.label.layout.display = 'none' 81 | self.label.layout.visibility = 'hidden' 82 | """ 83 | #self.target = widget(**kwargs) 84 | self.widget = widget(**kwargs)#wid.HBox(children=[self.target])# 85 | 86 | #self.widget.layout.width = self.target.layout.width 87 | #self.add_ids() 88 | self.visible = visible 89 | 90 | self.autoset_max_width() 91 | 92 | self.widget.layout.min_width = "100px" 93 | #shorthands for widge and value 94 | def __call__(self,**kwaargs): 95 | return self.widget.value 96 | def __getitem__(self,index): 97 | if index is None or isinstance(index,(int,bool)): 98 | return self.widget 99 | else: 100 | raise ValueError("index must be integer or None or bool") 101 | #Attributes for mimicking standard widget interface 102 | #---------------------------------------------------- 103 | @property 104 | def width(self): 105 | return self.widget.layout.width 106 | @width.setter 107 | def width(self,val): 108 | if isinstance(val,str): 109 | if not val[-1] =='%': 110 | if self.widget.layout.max_width is None: 111 | self.widget.layout.max_width = val 112 | else: 113 | self.widget.layout.max_width = str(max(float(self.widget.layout.max_width[:-2]), 114 | float(val[:-2])))+'px' 115 | self.widget.layout.width = val 116 | elif isinstance(val,(tuple,list)): 117 | self.widget.layout.width = val[0] 118 | self.widget.layout.max_width = val[1] 119 | 120 | 121 | 122 | @property 123 | def target(self): 124 | return self.widget 125 | @property 126 | def layout(self): 127 | return self.widget.layout 128 | 129 | @property 130 | def hack(self): 131 | return self._hack_widget 132 | @hack.setter 133 | def hack(self, val): 134 | self._hack_widget = val 135 | 136 | @property 137 | def value(self): 138 | """Get the value of the wrapped widget""" 139 | if hasattr(self.target, 'value'): 140 | return self.target.value 141 | @value.setter 142 | def value(self, val): 143 | if hasattr(self.target, 'value'): 144 | self.target.value = val 145 | 146 | @property 147 | def options(self): 148 | """Same interface as widgets but easier to iterate""" 149 | try: 150 | return self.target.options 151 | except AttributeError: 152 | return None 153 | @options.setter 154 | def options(self, val): 155 | try: 156 | self.target.options = val 157 | 158 | except AttributeError: 159 | try: 160 | self._update_options(val) 161 | except: 162 | pass 163 | 164 | @property 165 | def visible(self): 166 | """Easier visibility changing""" 167 | return self.widget.layout.visibility == 'visible' \ 168 | and self.widget.layout.display == '' 169 | @visible.setter 170 | def visible(self, val): 171 | """Easier visibility changing""" 172 | if val: 173 | self.widget.layout.visibility = 'visible' 174 | self.widget.layout.display = '' 175 | else: 176 | self.widget.layout.visibility = 'hidden' 177 | self.widget.layout.display = 'none' 178 | 179 | 180 | @property 181 | def description(self): 182 | """Same interface as widgets but easier to iterate""" 183 | return self.target.description 184 | 185 | @description.setter 186 | def description(self, val): 187 | """Same interface as widgets but easier to iterate""" 188 | self._description = val 189 | self.label = wid.HTML(value='
'+self._description+'
') 190 | if val == '': 191 | self.label.layout.display = 'none' 192 | self.label.layout.visibility = 'hidden' 193 | else: 194 | self.label.layout.display = '' 195 | self.label.layout.visibility = 'visible' 196 | 197 | @property 198 | def orientation(self): 199 | """Same interface as widgets but easier to iterate""" 200 | try: 201 | return self.target.orientation 202 | except AttributeError: 203 | return None 204 | @orientation.setter 205 | def orientation(self, val): 206 | """Same interface as widgets but easier to iterate""" 207 | try: 208 | self.target.orientation = val 209 | except AttributeError: 210 | pass 211 | 212 | def update(self, val): 213 | self.value = val 214 | 215 | def observe(self, func, names='value'): 216 | """A quickly way to add observe calls to the widget""" 217 | if isinstance(self.target, 218 | wid.Widget.widget_types['Jupyter.Button']): 219 | self.target.on_click(func) 220 | if hasattr(self.target, 'value'): 221 | self.target.observe(func, names=names) 222 | 223 | def autoset_max_width(self): 224 | if not isinstance(self.widget,(wid.Box,wid.Tab,wid.Accordion,wid.HTML,wid.Image)): 225 | self.widget.layout.max_width = '300px' 226 | self._max_width_px ='300px' 227 | self.widget.layout.min_width = '30px' 228 | self._min_width_px ='30px' 229 | #Methods 230 | #------------------------------ 231 | def _update_options(self, cols): 232 | """This is for avoiding trailet errors due to invalid selections 233 | when updating the widgets options values """ 234 | current = set(self.target.options) 235 | inter = current.intersection(set(cols)) 236 | if inter == set(()): 237 | oldopt = self.target.options + ['dummy'] 238 | self.target.options = oldopt 239 | self.value = ('dummy',) 240 | newopt = ['dummy'] + cols 241 | self.target.options = newopt 242 | self.value = (cols[0],) 243 | self.target.options = cols 244 | else: 245 | self.value = tuple(current.intersection(set(cols))) 246 | self.target.options = cols 247 | 248 | def add_ids(self): 249 | hack_id = self._hack_id 250 | class_tag = str(self.class_) 251 | if class_tag == '': 252 | class_tag = "" 253 | id_tag = str(self.id) 254 | if id_tag == '': 255 | child_id = hack_id 256 | else: 257 | child_id = id_tag 258 | javascript = """ 259 | function iterateChildren(c,level) { 260 | var i; 261 | level = level+1; 262 | for (i = 0; i < c.length; i++) { 263 | if (typeof c[i] != 'undefined') { 264 | if (typeof c[i].style != 'undefined') { 265 | c[i].id += '"""+child_id+"""'+"-"+level+"-"+i; 266 | } 267 | children = c[i].childNodes; 268 | iterateChildren(children,level) 269 | } 270 | } 271 | } 272 | 273 | function markChildren_"""+hack_id+"""(hack_id) { 274 | var widget = document.getElementById('"""+hack_id+"""').parentElement.parentElement; 275 | widget.id += "shao "; 276 | widget.id += '"""+id_tag+"""'; 277 | widget.classList.add('"""+class_tag+"""') ; 278 | var c = widget.childNodes; 279 | //iterateChildren(c,0); 280 | } 281 | var hack_id = 'H6D2B1S9C0G'; 282 | markChildren_"""+hack_id+"""(hack_id); 283 | """ 284 | self.update_hack(js=javascript) 285 | self.hack.visibility = 'hidden' 286 | 287 | def update_hack(self, 288 | hack_id=None, 289 | html=None, 290 | css=None, 291 | js=None): 292 | """updates css hack""" 293 | if not html is None: 294 | self.html = html 295 | if not js is None: 296 | self.js = js 297 | if not css is None: 298 | self.css = css 299 | if not hack_id is None: 300 | self._hack_id = hack_id 301 | value = '
'\ 302 | +''\ 303 | +''+self.html 304 | self.hack.value = value 305 | 306 | 307 | 308 | class Title(Widget): 309 | """Widget used to mimic the markwodn syntax of the notebook""" 310 | def __init__(self, value='Title', **kwargs): 311 | self._text = value 312 | kwargs['value'] = "

"+value+"

" 313 | Widget.__init__(self, widget=wid.HTML, **kwargs) 314 | @property 315 | def text(self): 316 | return self._text 317 | @text.setter 318 | def text(self,value): 319 | self._text = value 320 | self.value = "

"+value+"

" 321 | 322 | class SubTitle(Widget): 323 | """Widget used to mimic the markwodn syntax of the notebook""" 324 | def __init__(self, value='Title', **kwargs): 325 | self._text = value 326 | kwargs['value'] = "

"+value+"

" 327 | Widget.__init__(self, widget=wid.HTML, **kwargs) 328 | @property 329 | def text(self): 330 | return self._text 331 | @text.setter 332 | def text(self,value): 333 | self._text = value 334 | self.value = "

"+value+"

" 335 | 336 | class SubSubTitle(Widget): 337 | """Widget used to mimic the markwodn syntax of the notebook""" 338 | def __init__(self, value='Title', **kwargs): 339 | self._text = value 340 | kwargs['value'] = "

"+value+"

" 341 | Widget.__init__(self, widget=wid.HTML, **kwargs) 342 | @property 343 | def text(self): 344 | return self._text 345 | @text.setter 346 | def text(self,value): 347 | self._text = value 348 | self.value = "

"+value+"

" 349 | -------------------------------------------------------------------------------- /shaolin/core/kungfu.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import string 3 | import random 4 | import inspect 5 | import six 6 | import numpy as np 7 | import ipywidgets as wid 8 | from shaolin.core.shaoscript import shaoscript 9 | from shaolin.core.dashboard import Dashboard 10 | from shaolin.core.widgets import Title, SubTitle, SubSubTitle 11 | from shaolin.dashboards.colormap import ColormapPicker 12 | 13 | 14 | class KungFu(Dashboard): 15 | def __init__(self, 16 | name='dash', 17 | box='5c', 18 | interact=None, 19 | mode=None, 20 | func=None, 21 | dash=None, 22 | group_n=3, 23 | **kwargs): 24 | self._group_n = group_n 25 | self.__dic_mode = mode 26 | self.__interact = interact 27 | if self.__interact and mode is None: 28 | self.__dic_mode = 'interactive' 29 | if not func is None: 30 | a = inspect.getargspec(func) 31 | c_kwargs = dict(zip(a.args[-len(a.defaults):],a.defaults)) 32 | c_kwargs.update(kwargs) 33 | else: 34 | c_kwargs = kwargs 35 | 36 | children = self.get_children_widgets(c_kwargs) 37 | self.name = name 38 | dash = dash or self.process_children_layout(box,children)#dash or [box+'$n='+name,children] 39 | #print(dash) 40 | Dashboard.__init__(self,dash,name=name,mode=mode) 41 | self._func = func 42 | self.observe(self.fun) 43 | 44 | #shorthands for widget and value 45 | @staticmethod 46 | def is_text_widget(w): 47 | shao_titles = Title, SubTitle, SubSubTitle 48 | return isinstance(w,shao_titles) or isinstance(w[0],wid.Label) 49 | @staticmethod 50 | def compare_widgets(a,b): 51 | pass 52 | 53 | @staticmethod 54 | def _get_first_child(children): 55 | title = [] 56 | buttons = [] 57 | subtitle = [] 58 | subsubtitle = [] 59 | progress = [] 60 | for c in children: 61 | if isinstance(c,Title): 62 | title.append(c) 63 | elif isinstance(c,SubTitle): 64 | subtitle.append(c) 65 | elif isinstance(c,SubSubTitle): 66 | subsubtitle.append(c) 67 | elif isinstance(c.widget,(wid.FloatProgress,wid.IntProgress)): 68 | progress.append(c) 69 | elif isinstance(c.widget,wid.Button): 70 | buttons.append(c) 71 | first = title + subtitle +subsubtitle + progress +buttons 72 | #print(first) 73 | return first 74 | 75 | @staticmethod 76 | def _get_sliders_child(children): 77 | slid = [] 78 | slid_types = (wid.FloatSlider,wid.IntSlider,wid.IntText,wid.FloatText) 79 | for c in children: 80 | if isinstance(c.widget,slid_types): 81 | slid.append(c) 82 | return slid 83 | @staticmethod 84 | def _get_colors_child(children): 85 | 86 | colors = [] 87 | 88 | for c in children: 89 | if isinstance(c.widget,wid.ColorPicker) or isinstance(c,ColormapPicker): 90 | colors.append(c) 91 | return colors 92 | 93 | @staticmethod 94 | def _get_text_child(children): 95 | text = [] 96 | text_types = (wid.Text,wid.Textarea) 97 | for c in children: 98 | if isinstance(c.widget,text_types): 99 | text.append(c) 100 | return text 101 | 102 | @staticmethod 103 | def _get_selection_child(children): 104 | select = [] 105 | select_types = (wid.Select,wid.SelectionSlider, 106 | wid.Dropdown,wid.ToggleButtons, 107 | wid.SelectMultiple,wid.RadioButtons) 108 | for c in children: 109 | if isinstance(c.widget,select_types): 110 | select.append(c) 111 | return select 112 | 113 | @staticmethod 114 | def _get_bool_child(children): 115 | bools = [] 116 | bool_types = (wid.Checkbox,wid.ToggleButton,wid.Valid) 117 | for c in children: 118 | if isinstance(c.widget,bool_types): 119 | bools.append(c) 120 | return bools 121 | 122 | @staticmethod 123 | def _get_range_child(children): 124 | ranges = [] 125 | range_types = (wid.FloatRangeSlider,wid.IntRangeSlider) 126 | for c in children: 127 | if isinstance(c.widget,range_types): 128 | ranges.append(c) 129 | return ranges 130 | 131 | def create_boxes(self,children,is_col=True,num=5,name=None,child_names=None): 132 | def id_generator(size=6, chars=string.ascii_uppercase + string.digits): 133 | return ''.join(random.choice(chars) for _ in range(size)) 134 | 135 | 136 | name = name or id_generator() 137 | child_names = child_names or [id_generator() for _ in range(len(children))] 138 | if isinstance(is_col,bool): 139 | b = 'c$n='+name if is_col else 'r$n='+name 140 | if len(children)<=num: 141 | return [b,children] 142 | 143 | pases = int(np.floor(len(children)/num)) 144 | j = 0 145 | sub_children = [] 146 | for p in range(pases): 147 | sub = [] 148 | for j in range(p*num,p*num+num): 149 | sub.append(children[j]) 150 | sub_b = 'c$n='+id_generator() if not is_col else 'r$n='+id_generator() 151 | sub_children.append([sub_b,sub]) 152 | last_sub = [] 153 | for i in range(j+1,len(children)): 154 | last_sub.append(children[i]) 155 | sub_b = 'c$n='+id_generator() if not is_col else 'r$n='+id_generator() 156 | sub_children.append([sub_b,last_sub]) 157 | if isinstance(is_col,str): 158 | b = is_col+'$n='+name+'&t='+str(tuple(child_names)).replace('(',\ 159 | '').replace(')','').replace("'",'').replace('"','') 160 | return [b,children] 161 | return [b,sub_children] 162 | 163 | def group_children(self,children,is_col,num=5): 164 | #title and buttons 165 | #is_col = not is_col 166 | first_child = self._get_first_child(children) 167 | first_child_b = self.create_boxes(first_child,is_col,num,name='main') if len(first_child)>=1 else [] 168 | #print("first child:",first_child) 169 | #Sliders int and floar 170 | sliders = self._get_sliders_child(children) 171 | sliders_b = self.create_boxes(sliders,is_col,num,name='numeric') if len(sliders)>=1 else [] 172 | #print("sliders:",sliders) 173 | #text widget 174 | text = self._get_text_child(children) 175 | text_b = self.create_boxes(text,is_col,num,name='text') if len(text)>=1 else [] 176 | #print("text:",text) 177 | #selection widgets 178 | select = self._get_selection_child(children) 179 | select_b = self.create_boxes(select,is_col,num,name='selection') if len(select)>=1 else [] 180 | #print("select:",select) 181 | #boolean widgets 182 | bools = self._get_bool_child(children) 183 | bools_b = self.create_boxes(bools,is_col,num,name='booleans') if len(bools)>=1 else [] 184 | #color widgets 185 | colors = self._get_colors_child(children) 186 | colors_b = self.create_boxes(colors,is_col,num,name='colors') if len(colors)>=1 else [] 187 | #other widgets 188 | others = [] 189 | for c in children: 190 | if c not in first_child\ 191 | and c not in sliders and c not in text\ 192 | and c not in select and c not in bools and c not in colors: 193 | others.append(c) 194 | others_b = self.create_boxes(others,is_col,num,name='others') if len(others)>=1 else [] 195 | #print("bools:",bools) 196 | new_children = [] 197 | child_names = [] 198 | if first_child != []: 199 | new_children.append(first_child_b) 200 | child_names.append(self.name) 201 | if sliders != []: 202 | new_children.append(sliders_b) 203 | child_names.append('Numeric') 204 | if select != []: 205 | new_children.append(select_b) 206 | child_names.append('Options') 207 | if bools != []: 208 | new_children.append(bools_b) 209 | child_names.append('Boolean') 210 | if text != []: 211 | new_children.append(text_b) 212 | child_names.append('String') 213 | if colors != []: 214 | new_children.append(colors_b) 215 | child_names.append('Colors') 216 | if others != []: 217 | new_children.append(others_b) 218 | child_names.append('Other') 219 | return new_children,child_names 220 | 221 | def process_children_layout(self,box='5c',children=None): 222 | def filter_box_type(box): 223 | col_words = [ 'column','cols', 'col','c', 'vbox', 'v'] 224 | row_words = ['rows', 'row','r', 'HBox', 'box', 'h'] 225 | tabs_or_accord = ['accordion','accord','ac','a'] +['tabs','tab','t'] 226 | 227 | if '|' in box: 228 | box = box.replace('|','') 229 | group_ch = True 230 | else: 231 | group_ch = False 232 | is_col = True 233 | for w in row_words: 234 | if w in box.lower(): 235 | box = box.lower().replace(w,'') 236 | is_col = False 237 | for w in col_words: 238 | if w in box.lower(): 239 | box = box.lower().replace(w,'') 240 | 241 | for w in tabs_or_accord: 242 | if w in box.lower(): 243 | box = box.lower().replace(w,'') 244 | 245 | is_col = w 246 | if box !='': 247 | num = int(box) 248 | else: 249 | num=5 250 | return is_col,num,group_ch 251 | 252 | assert(isinstance(children,list)) 253 | #group the childfren 254 | is_col,num,group_ch = filter_box_type(box) 255 | if group_ch: 256 | rev = not is_col 257 | children, child_names = self.group_children(children,rev,num=num) 258 | #children like [form fi,sli,sel,bools,text] 259 | if isinstance(is_col,str): 260 | #two rows/cols with all the blockslen (child_names) 261 | return self.create_boxes(children,is_col,num=2,child_names=child_names) 262 | else: 263 | return self.create_boxes(children,is_col,num=num,child_names=child_names) 264 | return self.create_boxes(children,is_col,num) 265 | 266 | def fun(self,_=None): 267 | if not self._func is None and not self.__interact is None : 268 | return self._func(**self.kwargs) 269 | 270 | def kwargs_from_key(self,key): 271 | kws = {} 272 | if not self.__dic_mode is None and not 'mode' in kws.keys(): 273 | kws['mode'] = self.__dic_mode 274 | if key.startswith('@'): 275 | k = key[1:] 276 | kws['mode'] = 'interactive' 277 | elif key.startswith('I_'): 278 | k = key[2:] 279 | kws['mode'] = 'interactive' 280 | elif key.startswith('/'): 281 | k = key[1:] 282 | kws['mode'] = 'passive' 283 | elif key.startswith('P_'): 284 | k = key[2:] 285 | kws['mode'] = 'passive' 286 | else: 287 | k = key 288 | kws['name']=k 289 | kws['description']=k.capitalize().replace('_',' ') 290 | 291 | return kws 292 | 293 | def get_children_widgets(self,kwargs): 294 | def is_shaoscript(x): 295 | return "$" in x if isinstance(x,six.string_types) else False 296 | children = [] 297 | for k, v in kwargs.items(): 298 | kws = self.kwargs_from_key(k) 299 | if is_shaoscript(v): 300 | children.append(shaoscript(v,kws)) 301 | else: 302 | if isinstance(v,str): 303 | children.append(shaoscript('text$v='+v,kws)) 304 | else: 305 | children.append(shaoscript(v,kws)) 306 | return children 307 | 308 | @staticmethod 309 | def dict_to_children(self,kwargs): 310 | def is_shaoscript(x): 311 | return "$" in x if isinstance(x,six.string_types) else False 312 | children = [] 313 | for k, v in kwargs.items(): 314 | if is_shaoscript(v): 315 | children.append(shaoscript(v)) 316 | else: 317 | kws = dict(name=k,description=k.capitalize().replace('_',' ')) 318 | if not self.__dic_mode is None: 319 | kws['mode'] = self.__dic_mode 320 | if isinstance(v,str): 321 | children.append(shaoscript('text$v='+v,kws)) 322 | else: 323 | children.append(shaoscript(v,kws)) 324 | return children -------------------------------------------------------------------------------- /shaolin/core/shaoscript.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu May 19 12:03:50 2016 4 | 5 | @author: sergio 6 | """ 7 | 8 | import ast 9 | import six 10 | import ipywidgets as wid 11 | from shaolin.core.object_notation import object_notation 12 | from shaolin.core import widgets 13 | 14 | #from .widgets import widgets.Widget, widgets.Title, widgets.SubTitle, widgets.SubSubTitle 15 | 16 | def shaoscript(word, kwargs=None): 17 | """Return a shaolin widgets.Widget from a ShaoScript value. 18 | Parameters 19 | ---------- 20 | word : string, object 21 | String can be the name of a widgets.Widget in shaoscript syntax, or a string 22 | conaining the full definition of a widgets.Widget using the shaoscript syntax to 23 | also define its kwargs. 24 | kwargs: dict, default: None 25 | Contains the kwargs values for the widgets.Widget that will be returned. The 26 | key value parameters contained in the dict will be overriden by those 27 | defined in word. 28 | Returns 29 | ------- 30 | widgets.Widget: shaolin widgets.Widget. 31 | 32 | """ 33 | 34 | kwargs = kwargs or {} 35 | #create a widgets.Widget from a string. get its widgets.Widget type and kwargs 36 | if isinstance(word, six.string_types): 37 | word, kwargs = _handle_shaoscript_syntax(word, kwargs) 38 | #word and kwargs from shaoscript syntax 39 | #if the word corresponds to a widgets.Widget definition 40 | if isinstance(word, six.string_types): 41 | return _string_to_wiget(word, kwargs) 42 | #If word is already an ipywidgets.Widget class 43 | elif isinstance(word, tuple(wid.Widget.widget_types.values())): 44 | return widgets.Widget(word, **kwargs) 45 | #word has to be a python object representing object notation 46 | try: 47 | return object_notation(word, kwargs) 48 | except: 49 | raise ValueError('''Bad shaoscript syntax. \n 50 | Failed to convert word: {} with kwargs:{}.'''\ 51 | .format(word, kwargs)) 52 | 53 | def _handle_shaoscript_syntax(string, kwargs=None): 54 | """Return a string defining a shaolin widgets.Widget and a dictionary containinng 55 | its kwargs. 56 | Parameters 57 | ---------- 58 | string : string 59 | String can be the name of a widgets.Widget in shaoscript syntax, or a string 60 | conaining the full definition of a widgets.Widget using the shaoscript syntax to 61 | also define its kwargs. 62 | kwargs: dict, default: None 63 | Contains the kwargs values for the widgets.Widget that will be returned. The 64 | key value parameters contained in the dict will be overriden by those 65 | defined in word. 66 | Returns 67 | ------- 68 | word: string 69 | Contains only the type of the widgets.Widget in shaoscript notation. 70 | kwargs: dict 71 | Dictionary containing the kwargs for creating a shaolin widgets.Widget. 72 | 73 | Shaoscript custom parameters available 74 | -------------------------------------- 75 | paramters(aliases): value parsing 76 | 77 | 'options'('o', 'opt','opts'): ast.literal_eval 78 | 'description'('d','desc'): str 79 | 'id': str 80 | 'class_'('c','cls'): str 81 | 'visible'('vis'): boolean 82 | 'orientation'('ori','orient'): 'vertical','horizontal' 83 | 'name'('n'): str 84 | 'value'('val','v'): str 85 | val being a string means that non string values cannot be set this way. 86 | Use object notation in the definition of the widgets.Widget. 87 | 88 | """ 89 | kwargs = kwargs or {} 90 | #take into account interactivity 91 | main_key = string[0] 92 | if main_key == '@': 93 | kwargs['mode'] = 'interactive' 94 | sliced = string[1:] 95 | elif main_key == '/': 96 | kwargs['mode'] = 'active' 97 | sliced = string[1:] 98 | else: 99 | sliced = string 100 | word = sliced 101 | #separating widgets.Widget descriptor from atributes 102 | split = word.split('$') 103 | if _is_object_notation(split[0]): 104 | word = ast.literal_eval(split[0]) 105 | else: 106 | word = split[0] 107 | #string defines kwargs 108 | 109 | kwargs = shaoscript_to_kwargs(split[1], kwargs) if len(split) == 2 else kwargs 110 | return word, kwargs 111 | 112 | def _is_object_notation(string): 113 | """Checks if a string can be converted to object notation""" 114 | try: 115 | onw = ast.literal_eval(string) 116 | __ =object_notation(onw, {}) 117 | return True 118 | except: 119 | return False 120 | 121 | 122 | def shaoscript_to_kwargs(string, kwargs): 123 | params = string.split('&') 124 | for par in params: 125 | key, val = decode_param(par) 126 | kwargs[key] = val 127 | #name infered from description 128 | if 'description' in kwargs.keys()\ 129 | and 'name' not in kwargs.keys(): 130 | kwargs['name'] = kwargs['description'].lower().replace(' ', '_') 131 | #id infered from name 132 | if 'name' in kwargs.keys()\ 133 | and not 'id' in kwargs.keys(): 134 | kwargs['id'] = kwargs['name'].lower().replace('_', '-') 135 | return kwargs 136 | 137 | def decode_param(string): 138 | """ 139 | Converts a string representing a parameter in shaoscript syntax to a pair of key, value 140 | a valid parameter in shaoscript will have the following form: 141 | 142 | param --> 'name=val' 143 | There are some parameters that have custom parsing and are allowed aliases. 144 | The aliases are not case sensitive. 145 | 146 | Paramters(aliases): value parsing 147 | --------------------------------- 148 | 'options'('o', 'opt','opts'): ast.literal_eval 149 | 'description'('d','desc'): str 150 | 'id': str 151 | 'class_'('c','cls'): str 152 | 'visible'('vis'): boolean 153 | 'orientation'('ori','orient'): 'vertical','horizontal' 154 | 'name'('n'): str 155 | 'value'('val','v'): str 156 | val being a string means that non string values cannot be set this way. 157 | Use object notation in the definition of the widgets.Widget. 158 | 'placeholder'('ph','pholder'): str 159 | '_widgets.Titles'('widgets.Titles','t','widgets.Title','tit'): dict 160 | the val attribute will be the names of each widgets.Title separated by commas. 161 | no need to specify string simbols "" or '', as conversion will be taken 162 | care of internally. 163 | 164 | 165 | """ 166 | key, val = string.split('=') 167 | key = key.lower() 168 | if key in ['o','opt','opts','options']: 169 | name = 'options' 170 | val = ast.literal_eval(val) 171 | elif key in ['d','desc', 'description']: 172 | name = 'description' 173 | elif key == 'id': 174 | name = 'id' 175 | elif key in ['continuous_update', 'cu','cont','cupdate']: 176 | name = 'continuous_update' 177 | val = True if val in ['1','True'] else False 178 | elif key in ['class_','cls']: 179 | name = 'class_' 180 | elif key in ['visible', 'vis']: 181 | name = 'visible' 182 | val = 'visible' if val in ['0', 'False','None'] else 'hidden' 183 | elif key in ['ori', 'orientation','orient']: 184 | name = 'orientation' 185 | if val in ['v','vert', 'vertical']: 186 | val = 'vertical' 187 | elif val in ['h','hori', 'horizontal']: 188 | val = 'horizontal' 189 | elif key in ['n', 'name']: 190 | name = 'name' 191 | elif key in ['v','val', 'value']: 192 | name = 'value' 193 | #val = ast.literal_eval(val) 194 | elif key in ['mode', 'm']: 195 | name = 'mode' 196 | elif key in ['placeholder','ph','pholder']: 197 | name='placeholder' 198 | elif key in ['_titles','title','t','widget_titles','tit']: 199 | name = '_titles' 200 | widgets.Titles_names = val.split(',') 201 | val = dict(zip(range(len(widgets.Titles_names)),widgets.Titles_names)) 202 | else: 203 | name = key 204 | val = ast.literal_eval(val) 205 | return name, val 206 | 207 | def _string_to_wiget(word, kwargs): 208 | def create_colormap(kwargs): 209 | from shaolin.dashboards import colormap as cmap 210 | if 'id' in kwargs.keys(): 211 | del kwargs['id'] 212 | return cmap.ColormapPicker(**kwargs) 213 | """Creates a shaolin widgets.Widget from a string and a dictionary of kwargs""" 214 | assert isinstance(word, six.string_types) 215 | word = word.lower() 216 | #Layout 217 | #--------------------------------- 218 | if word in ['c', 'col', 'column', 'vbox', 'v']: 219 | if not 'mode' in kwargs.keys(): 220 | kwargs['mode'] = 'passive' 221 | return widgets.Widget(wid.VBox, **kwargs) 222 | elif word in ['r', 'row', 'HBox', 'box', 'h']: 223 | if not 'mode' in kwargs.keys(): 224 | kwargs['mode'] = 'passive' 225 | return widgets.Widget(wid.HBox, **kwargs) 226 | #Markdown 227 | #-------------------------------- 228 | elif word in ['widgets.SubSubTitle', 'h3', '###', 'subsub', 'ss']: 229 | if not 'mode' in kwargs.keys(): 230 | kwargs['mode'] = 'passive' 231 | return widgets.SubSubTitle(**kwargs) 232 | 233 | elif word[:3] == '###': 234 | if not 'mode' in kwargs.keys(): 235 | kwargs['mode'] = 'passive' 236 | if not 'name' in kwargs.keys(): 237 | kwargs['name'] = word[3:].lower().replace(' ', '_') 238 | if not 'id' in kwargs.keys(): 239 | kwargs['id'] = kwargs['name'].lower().replace('_', '-') 240 | return widgets.SubSubTitle(value=word[3:], **kwargs) 241 | 242 | elif word in ['widgets.SubTitle', 'h2', '##', 'sub', 's']: 243 | if not 'mode' in kwargs.keys(): 244 | kwargs['mode'] = 'passive' 245 | return widgets.SubTitle(**kwargs) 246 | 247 | elif word[:2] == '##': 248 | if not 'mode' in kwargs.keys(): 249 | kwargs['mode'] = 'passive' 250 | if not 'name' in kwargs.keys(): 251 | kwargs['name'] = word[2:].lower().replace(' ', '_') 252 | if not 'id' in kwargs.keys(): 253 | kwargs['id'] = kwargs['name'].lower().replace('_', '-') 254 | return widgets.SubTitle(value=word[2:], **kwargs) 255 | 256 | elif word in ['widgets.Title', 'h1', '#']: 257 | if not 'mode' in kwargs.keys(): 258 | kwargs['mode'] = 'passive' 259 | return widgets.Title(**kwargs) 260 | 261 | elif word[:1] == '#': 262 | if not 'mode' in kwargs.keys(): 263 | kwargs['mode'] = 'passive' 264 | if not 'name' in kwargs.keys(): 265 | kwargs['name'] = word[1:].lower().replace(' ', '_') 266 | if not 'id' in kwargs.keys(): 267 | kwargs['id'] = kwargs['name'].lower().replace('_', '-') 268 | return widgets.Title(value=word[1:], **kwargs) 269 | 270 | #Int and float 271 | #-------------------------------- 272 | elif word in ['float_slider', 'floatslider', 'fsld', 'fs']: 273 | return widgets.Widget(wid.FloatSlider, **kwargs) 274 | elif word in ['float_text', 'floattext', 'ftxt', 'ft']: 275 | return widgets.Widget(wid.FloatText, **kwargs) 276 | elif word in ['int_slider', 'intslider', 'isld', 'is']: 277 | return widgets.Widget(wid.IntSlider, **kwargs) 278 | elif word in ['int_text', 'inttext', 'itxt', 'it']: 279 | return widgets.Widget(wid.IntText, **kwargs) 280 | #Range 281 | #-------------------------------- 282 | elif word in ['float_range', 'floatprogress', 'fprog', 'fp']: 283 | return widgets.Widget(wid.FloatRangeSlider, **kwargs) 284 | elif word in ['int_range', 'intrange', 'irng', 'ir']: 285 | return widgets.Widget(wid.IntRangeSlider, **kwargs) 286 | #Progress 287 | #-------------------------------- 288 | elif word in ['float_progress', 'floatprogress', 'fprog', 'fp']: 289 | return widgets.Widget(wid.FloatProgress, **kwargs) 290 | elif word in ['int_progress', 'intprogress', 'iprog', 'ip']: 291 | return widgets.Widget(wid.IntProgress, **kwargs) 292 | #Button 293 | #-------------------------------- 294 | elif word in ['button', 'btn', 'b']: 295 | return widgets.Widget(wid.Button, **kwargs) 296 | #string and color 297 | #--------------- 298 | elif word in ['text', 'txt','str','string']: 299 | return widgets.Widget(wid.Text, **kwargs) 300 | elif word in ['color', 'colorpicker','cp','cpicker']: 301 | return widgets.Widget(wid.ColorPicker, **kwargs) 302 | #colormap 303 | 304 | 305 | elif word in ['cm', 'cmap','colormap','cmappicker']: 306 | return create_colormap(kwargs) 307 | 308 | #Options for pseudo tabs creation 309 | #-------------------------------- 310 | #""" 311 | #elif word in ['radio_display_selection','r_ds','radio_ds']: 312 | # return RadioDisplaySelection(**kwargs) 313 | #elif word in ['toggle_display_selection','t_ds','toggle_ds']: 314 | # return ToggleDisplaySelection(**kwargs) 315 | #elif word in ['display_selection','ds','dsel']: 316 | # return DisplaySelection(**kwargs) 317 | 318 | #""" 319 | #Selectors 320 | #-------------------------- 321 | elif word in ['select_multiple', 'selmul', 'sm']: 322 | return widgets.Widget(wid.SelectMultiple, **kwargs) 323 | elif word in ['select', 'sel']: 324 | return widgets.Widget(wid.Select, **kwargs) 325 | elif word in ['dropdown', 'dd', 'ddown']: 326 | return widgets.Widget(wid.Dropdown, **kwargs) 327 | elif word in ['selection_slider', 'selslider', 'ss']: 328 | return widgets.Widget(wid.SelectionSlider, **kwargs) 329 | elif word in ['toggle_button', 'toggle', 'tog']: 330 | return widgets.Widget(wid.ToggleButton, **kwargs) 331 | elif word in ['toggle_buttons', 'toggles', 'togs']: 332 | return widgets.Widget(wid.ToggleButtons, **kwargs) 333 | elif word in ['radio_buttons', 'radio', 'rad','rs']: 334 | return widgets.Widget(wid.RadioButtons, **kwargs) 335 | elif word in ['html', 'HTML']: 336 | return widgets.Widget(wid.HTML, **kwargs) 337 | elif word in ['TextArea', 'texta', 'textarea', 'text_area']: 338 | return widgets.Widget(wid.Textarea, **kwargs) 339 | 340 | elif word in ['tex','latex']: 341 | kwargs['value'] = '$$'+str(kwargs['value'])+'$$' 342 | if not 'mode' in kwargs.keys(): 343 | kwargs['mode'] = 'passive' 344 | return widgets.Widget(wid.Label, **kwargs) 345 | elif word in ['tab','t','tabs']: 346 | if not 'mode' in kwargs.keys(): 347 | kwargs['mode'] = 'passive' 348 | return widgets.Widget(wid.Tab, **kwargs) 349 | elif word in ['accordion','accord','tabs','ac','a']: 350 | if not 'mode' in kwargs.keys(): 351 | kwargs['mode'] = 'passive' 352 | return widgets.Widget(wid.Accordion, **kwargs) 353 | 354 | elif word in ['datetime','datepicker','date','dpicker','dp']: 355 | return widgets.Widget(wid.DatePicker, **kwargs) 356 | else: 357 | if not 'value' in kwargs.keys(): 358 | kwargs['value'] = word 359 | if not 'mode' in kwargs.keys(): 360 | kwargs['mode'] = 'passive' 361 | return widgets.Widget(wid.Label, **kwargs) 362 | else: 363 | return widgets.Widget(wid.Label, **kwargs) 364 | -------------------------------------------------------------------------------- /shaolin/dashboards/bokeh.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Jun 1 23:37:47 2016 4 | 5 | @author: Guillem Duran Ballester for HCSoft 6 | """ 7 | import pandas as pd 8 | from IPython.core.display import display, clear_output 9 | from bokeh.models import HoverTool 10 | import bokeh.models.sources as bks 11 | from bokeh.plotting import figure, show 12 | from bokeh.io import push_notebook, output_notebook 13 | from bokeh.embed import notebook_div 14 | from shaolin.core.dashboard import Dashboard, ToggleMenu 15 | from shaolin.dashboards.plot_mappers import PlotMapper 16 | from shaolin.core.shaoscript import shaoscript 17 | 18 | class BokehDataFrameTooltip(Dashboard): 19 | 20 | def __init__(self, data, mode='interactive', **kwargs): 21 | self._data = data 22 | dash = ['c$N=tooltip', 23 | ['###Tolltip$N=title', 24 | '@selmul$n=tooltip_cols&d=Tooltip info&o='+str(tuple(data.columns.values)) 25 | 26 | ] 27 | ] 28 | self.output = data.copy() 29 | Dashboard.__init__(self, dash, mode=mode, **kwargs) 30 | self.tooltip_cols.value = tuple(data.columns.values) 31 | self.observe(self.update) 32 | self.update() 33 | 34 | @property 35 | def data(self): 36 | return self._data 37 | @data.setter 38 | def data(self, val): 39 | self._data = val 40 | self.update() 41 | def update(self, _=None): 42 | self.output = self._data[list(self.tooltip_cols.value)] 43 | 44 | def create_tooltip(self): 45 | """A function for creating a tooltip suitable for the plot. This means 46 | that by default all kinds of plots should try to include tooltips 47 | """ 48 | return [("index", "$index")] + [(x, '@'+x) for x in self.output.columns] 49 | 50 | class ScatterPlot(ToggleMenu): 51 | 52 | def __init__(self, data,name='scatter_plot', **kwargs): 53 | output_notebook(hide_banner=True) 54 | self._data = data 55 | mapper = PlotMapper(data, button_type='ddown',button_pos='top', name='mapper', mode='interactive') 56 | if isinstance(data, pd.DataFrame): 57 | tooltip = BokehDataFrameTooltip(data, name='tooltip', mode='interactive') 58 | ToggleMenu.__init__(self, children=[mapper,tooltip], name=name,**kwargs) 59 | else: 60 | ToggleMenu.__init__(self, children=[mapper], name=name,**kwargs) 61 | self.buttons.value = 'mapper' 62 | self.mapper.buttons.value = 'y' 63 | if isinstance(self._data,pd.DataFrame): 64 | self.mapper.y.data_slicer.columns_slicer.dd_selector.value =\ 65 | self.mapper.y.data_slicer.columns_slicer.dd_selector.target.options[1] 66 | self.observe(self.update) 67 | self.mapper.marker.marker_type.observe(self._on_marker_change) 68 | 69 | self.update_source_df() 70 | self.init_plot() 71 | self.update() 72 | 73 | def _on_marker_change(self, _=None): 74 | clear_output() 75 | self.init_plot() 76 | self.update() 77 | return display(show(self.plot)) 78 | 79 | @property 80 | def data(self): 81 | return self._data 82 | 83 | def update_source_df(self): 84 | """Datasources for plots managing""" 85 | if isinstance(self._data, pd.DataFrame): 86 | self.output= self.mapper.output.join(self.tooltip.output) 87 | else: 88 | self.output= self.mapper.output 89 | 90 | def update_tooltips(self): 91 | """Update tooltip data and inject it into the plot tooltips""" 92 | if isinstance(self._data, pd.DataFrame): 93 | self.plot.tools[-1].tooltips = self.tooltip.create_tooltip() 94 | 95 | def update(self, _=None): 96 | """Set up all the combined elements needed for the plot""" 97 | self.update_source_df() 98 | if isinstance(self._data, pd.DataFrame): 99 | self.update_tooltips() 100 | self.push_data() 101 | 102 | def push_data(self): 103 | """A function to push the content of the source DataFrame 104 | to a specific plot source 105 | """ 106 | self.bokeh_source.data = dict([(x, self.output[x].values) for x in self.output.columns]) 107 | self.plot.xaxis.axis_label = self.mapper.x.data_slicer.description 108 | self.plot.yaxis.axis_label = self.mapper.y.data_slicer.description 109 | 110 | push_notebook() 111 | 112 | def init_plot(self): 113 | """Handle plot init""" 114 | self.bokeh_source = bks.ColumnDataSource(dict([(x, self.output[x].values)\ 115 | for x in self.output.columns])) 116 | if isinstance(self._data, pd.DataFrame): 117 | tooltip = self.tooltip.create_tooltip() 118 | 119 | self.plot = figure(title="Scatter plot", width=600, height=600, webgl=False, 120 | tools="pan,wheel_zoom,box_zoom,reset,resize,crosshair",) 121 | self.plot.xaxis.axis_label = self.mapper.x.data_slicer.description 122 | self.plot.yaxis.axis_label = self.mapper.y.data_slicer.description 123 | 124 | #marker = self.marker_free_sel.marker.value 125 | 126 | _scatter = self.plot.scatter(source=self.bokeh_source, 127 | x='x', y='y', 128 | line_color='line_color', 129 | fill_color='fill_color', 130 | fill_alpha='fill_alpha', 131 | line_alpha='line_alpha', 132 | size='size', 133 | line_width='line_width', 134 | marker=self.mapper.marker.marker_type.value 135 | 136 | ) 137 | if isinstance(self._data, pd.DataFrame): 138 | self.plot.add_tools(HoverTool(tooltips=tooltip, renderers=[_scatter])) 139 | 140 | def show(self): 141 | return display(self.widget, show(self.plot)) 142 | 143 | @property 144 | def snapshot(self, name='bokeh_scatter'): 145 | html = notebook_div(self.plot) 146 | widget = shaoscript('html$N='+name) 147 | widget.value = html 148 | return widget 149 | 150 | class GraphPlotBokeh(ToggleMenu): 151 | 152 | def __init__(self, gc, name='scatter_plot', **kwargs): 153 | node_mapper_dict = {'size':{'max':100, 154 | 'min':5, 155 | 'step':0.5, 156 | 'high':75, 157 | 'low':25, 158 | 'default':60, 159 | 'map_data':False, 160 | 'fixed_active':False, 161 | }, 162 | 'line_width':{'max':50, 163 | 'min':0, 164 | 'step':0.5, 165 | 'high':5, 166 | 'low':1, 167 | 'default':2, 168 | 'map_data':False, 169 | 'fixed_active':False, 170 | }, 171 | 'fill_alpha':{'max':1.0, 172 | 'min':0., 173 | 'step':0.05, 174 | 'high':0.95, 175 | 'low':0.3, 176 | 'default':1., 177 | 'map_data':False, 178 | 'fixed_active':False, 179 | }, 180 | 'line_alpha':{'max':1.0, 181 | 'min':0., 182 | 'step':0.05, 183 | 'high':0.95, 184 | 'low':0.3, 185 | 'default':1., 186 | 'map_data':False, 187 | 'fixed_active':False, 188 | }, 189 | 'line_color':{'default_color':'black','map_data':False,'step':0.05,'min':0.0,'low':0.0}, 190 | 'fill_color':{'default_color':'#11D4CA','map_data':False,'step':0.05,'min':0.0,'low':0.0} 191 | } 192 | edge_mapper_dict = {'size':{'max':100, 193 | 'min':5, 194 | 'step':0.5, 195 | 'high':20, 196 | 'low':7, 197 | 'default':7, 198 | 'map_data':False, 199 | 'fixed_active':False, 200 | }, 201 | 'line_width':{'max':50, 202 | 'min':0, 203 | 'step':0.5, 204 | 'high':5, 205 | 'low':1, 206 | 'default':2, 207 | 'map_data':False, 208 | 'fixed_active':False, 209 | }, 210 | 'fill_alpha':{'max':1.0, 211 | 'min':0., 212 | 'step':0.05, 213 | 'high':0.95, 214 | 'low':0.3, 215 | 'default':1., 216 | 'map_data':False, 217 | 'fixed_active':False, 218 | }, 219 | 'line_alpha':{'max':1.0, 220 | 'min':0., 221 | 'step':0.05, 222 | 'high':0.95, 223 | 'low':0.3, 224 | 'default':1., 225 | 'map_data':False, 226 | 'fixed_active':False, 227 | }, 228 | 'line_color':{'default_color':'black','map_data':False,'step':0.05,'min':0.0,'low':0.0}, 229 | 'fill_color':{'default_color':'#EDB021','map_data':False,'step':0.05,'min':0.0,'low':0.0} 230 | } 231 | gc.name = 'gc' 232 | output_notebook(hide_banner=True) 233 | edge_mapper_data = self.prepare_edge_mapper_data(gc) 234 | node_mapper = PlotMapper(gc.node, mapper_dict=node_mapper_dict, button_type='ddown',button_pos='top', name='node_mapper', mode='interactive') 235 | edge_mapper = PlotMapper(edge_mapper_data, mapper_dict=edge_mapper_dict, button_type='ddown',button_pos='top', name='edge_mapper', mode='interactive') 236 | node_tooltip_data = gc.node.combine_first(gc.node_metrics.T) 237 | node_tooltip = BokehDataFrameTooltip(node_tooltip_data, name='node_tooltip') 238 | edge_tooltip = BokehDataFrameTooltip(edge_mapper_data, name='edge_tooltip') 239 | ToggleMenu.__init__(self, 240 | children=[gc,node_mapper, 241 | edge_mapper, 242 | node_tooltip, 243 | edge_tooltip], 244 | name=name,**kwargs) 245 | 246 | self.observe(self.update) 247 | self.gc.calculate.observe(self.update) 248 | self.node_mapper.marker.marker_type.observe(self._on_marker_change) 249 | self.edge_mapper.marker.marker_type.observe(self._on_marker_change) 250 | self.update_source_df() 251 | self.init_plot() 252 | self.update() 253 | self._init_layout() 254 | 255 | def prepare_edge_mapper_data(self,gc): 256 | dft = gc.edge.to_frame().reset_index() 257 | ti = list(zip(dft.minor.values,dft.major.values)) 258 | dft.index = ti 259 | dft = dft.drop(['major','minor'],axis=1) 260 | return dft.ix[gc.G.edges()].copy() 261 | 262 | def _init_layout(self): 263 | params = ['size', 'line_width', 'fill_alpha', 'line_alpha', 'line_color', 'fill_color'] 264 | for target in ['node','edge']: 265 | mapper = getattr(self,target+'_mapper') 266 | for p in params: 267 | getattr(mapper,p).data_slicer.index_slicer.visible = False 268 | 269 | def update_source_df(self): 270 | """Datasources for plots managing""" 271 | def index_to_columns(df): 272 | old_index = df.index 273 | new_index = pd.MultiIndex.from_tuples(df.index) 274 | df.index = new_index 275 | df = df.reset_index() 276 | df.index = old_index 277 | columns = df.columns.values 278 | columns[:2] = ['major','minor'] 279 | df.columns = columns 280 | return df 281 | def fix_pos_index(edge_pos,edge_source): 282 | changed = set(edge_source.index) - set(edge_pos.index) 283 | edge_source.index = pd.MultiIndex.from_tuples(edge_source.index) 284 | edge_pos.index = pd.MultiIndex.from_tuples(edge_pos.index) 285 | for e in changed: 286 | inv = (e[1],e[0]) 287 | edge_pos.loc[inv,'minor'] = e[1] 288 | edge_pos.loc[inv,'major'] = e[0] 289 | return edge_pos 290 | self.node_source= self.node_mapper.output.join(self.node_tooltip.output) 291 | #self.edge_tooltip.output.index = pd.MultiIndex.from_tuples(self.edge_tooltip.output.index.values) 292 | #self.edge_mapper.output.index = pd.MultiIndex.from_tuples(self.edge_mapper.output.index.values) 293 | self.edge_source= self.edge_mapper.output.join(self.edge_tooltip.output) 294 | 295 | node_pos = self.gc.layout.node['2d'].dropna(axis=1).copy() 296 | edge_pos = self.gc.layout.edge['2d'].copy() 297 | edge_pos = index_to_columns(edge_pos) 298 | edge_source = index_to_columns(self.edge_source) 299 | edge_pos = fix_pos_index(edge_pos,edge_source) 300 | self.output_node = pd.concat([self.node_source, node_pos], axis=1).fillna('NaN').copy() 301 | self.output_edge = edge_source.merge(edge_pos,on=['major','minor'], left_index=True).fillna('NaN').copy()#edge_pos.merge(self.edge_source,on=['major','minor'],left_index=True) 302 | 303 | 304 | def update_mappers(self): 305 | dft = self.gc.edge.to_frame().reset_index() 306 | ti = list(zip(dft.minor.values,dft.major.values)) 307 | dft.index = ti 308 | dft = dft.drop(['major','minor'],axis=1) 309 | edge_mapper_data = dft.ix[self.gc.G.edges()].copy() 310 | self.edge_mapper.data = edge_mapper_data 311 | self.node_mapper.data = self.gc.node 312 | self.node_tooltip.data = self.gc.node_metrics.combine_first(self.gc.node.T).T 313 | self.edge_tooltip.data = edge_mapper_data 314 | 315 | def update_tooltips(self): 316 | """Update tooltip data and inject it into the plot tooltips""" 317 | self.plot.tools[-1].tooltips = self.edge_tooltip.create_tooltip() 318 | self.plot.tools[-2].tooltips = self.node_tooltip.create_tooltip() 319 | 320 | def update(self, _=None): 321 | """Set up all the combined elements needed for the plot""" 322 | self.update_mappers() 323 | self.update_source_df() 324 | self.update_tooltips() 325 | self.push_data() 326 | 327 | def push_data(self): 328 | """A function to push the content of the source DataFrame 329 | to a specific plot source 330 | """ 331 | self.node_bokeh_source.data = dict([(x, self.output_node[x].values) for x in self.output_node.columns]) 332 | self.edge_bokeh_source.data = dict([(x, self.output_edge[x].values) for x in self.output_edge.columns]) 333 | 334 | 335 | push_notebook() 336 | 337 | def _on_marker_change(self, _=None): 338 | clear_output() 339 | self.init_plot() 340 | self.update() 341 | return display(show(self.plot)) 342 | 343 | def init_plot(self): 344 | """Handle plot init""" 345 | self.node_bokeh_source = bks.ColumnDataSource(dict([(x, 346 | self.output_node[x].values)\ 347 | for x in self.output_node.columns])) 348 | self.edge_bokeh_source = bks.ColumnDataSource(dict([(x, 349 | self.output_edge[x].values)\ 350 | for x in self.output_edge.columns])) 351 | n_ttip = self.node_tooltip.create_tooltip() 352 | e_ttip = self.edge_tooltip.create_tooltip() 353 | 354 | self.plot = figure(title="Graph plot", width=600, height=600, webgl=False, 355 | tools="pan,wheel_zoom,box_zoom,reset,resize,crosshair",) 356 | 357 | #node_marker = 'circle'#self.node_marker_free_sel.marker.value 358 | #edge_marker = self.edge_marker_free_sel.marker.value 359 | 360 | self.plot.segment('x0', 'y0', 361 | 'x1', 'y1', 362 | color='line_color', 363 | line_width='line_width', 364 | alpha='line_alpha', 365 | source=self.edge_bokeh_source) 366 | 367 | edg_center = self.plot.scatter(source=self.edge_bokeh_source, 368 | x='cx', y='cy', 369 | line_color='line_color', 370 | fill_color='fill_color', 371 | alpha='fill_alpha', 372 | size='size', 373 | line_width='line_width', 374 | marker=self.edge_mapper.marker.marker_type.value 375 | )#, 376 | #marker=edge_marker) 377 | 378 | nod = self.plot.scatter(source=self.node_bokeh_source, 379 | x='x', y='y', 380 | line_color='line_color', 381 | fill_color='fill_color', 382 | fill_alpha='fill_alpha', 383 | size='size', 384 | line_width='line_width',#, 385 | marker=self.node_mapper.marker.marker_type.value) 386 | 387 | self.plot.text(source=self.node_bokeh_source, 388 | x='x', y='y', 389 | text='label', 390 | text_align='center') 391 | 392 | self.plot.add_tools(HoverTool(tooltips=n_ttip, renderers=[nod])) 393 | self.plot.add_tools(HoverTool(tooltips=e_ttip, renderers=[edg_center])) 394 | @property 395 | def snapshot(self, name='bokeh_scatter'): 396 | html = notebook_div(self.plot) 397 | widget = shaoscript('html$N='+name) 398 | widget.value = html 399 | return widget 400 | 401 | def show(self): 402 | return display(self.widget, show(self.plot)) --------------------------------------------------------------------------------