SlideShare uma empresa Scribd logo
1 de 165
Baixar para ler offline
Bowtie
Interactive Dashboards
Jacques Kvam
2017-05-25
1 / 50
Anonymous Chat
https://bowtie-chat.herokuapp.com
2 / 50
Who am I?
3 / 50
Who am I?
Computer Engineer turned "Data Scientist".
3 / 50
Who am I?
Computer Engineer turned "Data Scientist".
Work at energy analytics startup, Verdigris Technologies.
3 / 50
Who am I?
Computer Engineer turned "Data Scientist".
Work at energy analytics startup, Verdigris Technologies.
Heavy Python user for 3-5 years.
3 / 50
Who am I?
Computer Engineer turned "Data Scientist".
Work at energy analytics startup, Verdigris Technologies.
Heavy Python user for 3-5 years.
I'm not a frontend developer.
3 / 50
Agenda
4 / 50
Agenda
Motivation
4 / 50
Agenda
Motivation
A quick start
4 / 50
Agenda
Motivation
A quick start
Rapid prototyping tips
4 / 50
Agenda
Motivation
A quick start
Rapid prototyping tips
Advanced features
4 / 50
Agenda
Motivation
A quick start
Rapid prototyping tips
Advanced features
How to deploy
4 / 50
Agenda
Motivation
A quick start
Rapid prototyping tips
Advanced features
How to deploy
Tech stack
4 / 50
Agenda
Motivation
A quick start
Rapid prototyping tips
Advanced features
How to deploy
Tech stack
Future work and goals
4 / 50
Agenda
Motivation
A quick start
Rapid prototyping tips
Advanced features
How to deploy
Tech stack
Future work and goals
Will not be discussing similar tools.
4 / 50
Motivation
5 / 50
Motivation
Want to click on a chart and generate another chart.
5 / 50
Motivation
Want to click on a chart and generate another chart.
5 / 50
Tool Survey
6 / 50
Tool Survey
Don't want to use R!
6 / 50
Tool Survey
Don't want to use R!
Looked for solutions in Python.
6 / 50
Tool Survey
Don't want to use R!
Looked for solutions in Python.
Thought this should be easier.
6 / 50
Tool Survey
Don't want to use R!
Looked for solutions in Python.
Thought this should be easier.
Thought it would be fun to write something.
6 / 50
7 / 50
Initial Thoughts
8 / 50
Initial Thoughts
Plotly charts have lots of events: selection, click, and hover.
8 / 50
Initial Thoughts
Plotly charts have lots of events: selection, click, and hover.
Just need to communicate between Python and JS in browser.
8 / 50
Initial Thoughts
Plotly charts have lots of events: selection, click, and hover.
Just need to communicate between Python and JS in browser.
Socket.io seems like it could do the trick.
8 / 50
Initial Thoughts
Plotly charts have lots of events: selection, click, and hover.
Just need to communicate between Python and JS in browser.
Socket.io seems like it could do the trick.
That's good enough for a proof of concept.
8 / 50
Fast forward a few months
9 / 50
Your First Bowtie App
10 / 50
Your First Bowtie App
Each app has three parts
10 / 50
Your First Bowtie App
Each app has three parts
Choose the components in your app.
10 / 50
Your First Bowtie App
Each app has three parts
Choose the components in your app.
Write the callbacks (in response to events).
10 / 50
Your First Bowtie App
Each app has three parts
Choose the components in your app.
Write the callbacks (in response to events).
Layout the components and connect everything.
10 / 50
First we need some prereqs
11 / 50
First we need some prereqs
Need Node to get us yarn and webpack.
$ brew install node
$ npm install -g webpack
$ brew install yarn
Sorry for the MacOS bias.
11 / 50
First we need some prereqs
Need Node to get us yarn and webpack.
$ brew install node
$ npm install -g webpack
$ brew install yarn
Sorry for the MacOS bias.
Install Bowtie.
$ pip install bowtie
Works on Python 2 and 3
11 / 50
12 / 50
Select the components
13 / 50
Select the components
These are the widgets that exist in your app.
13 / 50
Select the components
These are the widgets that exist in your app.
Full list of components on readthedocs.
13 / 50
Select the components
These are the widgets that exist in your app.
Full list of components on readthedocs.
Split into two categories: visual widgets and controller widgets.
13 / 50
Select the components
These are the widgets that exist in your app.
Full list of components on readthedocs.
Split into two categories: visual widgets and controller widgets.
Visual: Plotly, SVG (matplotlib), Tables
13 / 50
Select the components
These are the widgets that exist in your app.
Full list of components on readthedocs.
Split into two categories: visual widgets and controller widgets.
Visual: Plotly, SVG (matplotlib), Tables
Controllers: DatePickers, Dropdown, Text, Sliders, Toggle, and a Button.
13 / 50
Select the components
These are the widgets that exist in your app.
Full list of components on readthedocs.
Split into two categories: visual widgets and controller widgets.
Visual: Plotly, SVG (matplotlib), Tables
Controllers: DatePickers, Dropdown, Text, Sliders, Toggle, and a Button.
from bowtie.visual import Plotly
from bowtie.control import Dropdown
plot = Plotly()
ddown = Dropdown()
13 / 50
What do these components do?
14 / 50
What do these components do?
Instructions for displaying itself in a webpage.
14 / 50
What do these components do?
Instructions for displaying itself in a webpage.
Commands, pre xed with do_, to update the state of the widget.
14 / 50
What do these components do?
Instructions for displaying itself in a webpage.
Commands, pre xed with do_, to update the state of the widget.
Events, pre xed with on_, to run python in response to.
14 / 50
What do these components do?
Instructions for displaying itself in a webpage.
Commands, pre xed with do_, to update the state of the widget.
Events, pre xed with on_, to run python in response to.
Getters, pre xed with get, gets the current states of the widget.
14 / 50
What do these components do?
Instructions for displaying itself in a webpage.
Commands, pre xed with do_, to update the state of the widget.
Events, pre xed with on_, to run python in response to.
Getters, pre xed with get, gets the current states of the widget.
For example: Dropdown docs.
14 / 50
De ne the callbacks
15 / 50
De ne the callbacks
We'll de ne functions to get run when events happen.
15 / 50
De ne the callbacks
We'll de ne functions to get run when events happen.
import plotlywrapper as pw
def callback(item):
chart = pw.line(range(item['value']))
plot.do_all(chart.dict)
15 / 50
De ne the callbacks
We'll de ne functions to get run when events happen.
import plotlywrapper as pw
def callback(item):
chart = pw.line(range(item['value']))
plot.do_all(chart.dict)
We'll run this function in response to a dropdown event.
15 / 50
De ne the callbacks
We'll de ne functions to get run when events happen.
import plotlywrapper as pw
def callback(item):
chart = pw.line(range(item['value']))
plot.do_all(chart.dict)
We'll run this function in response to a dropdown event.
The passed object for this dropdown is a dictionary with two keys: "label" and "value".
15 / 50
De ne the callbacks
We'll de ne functions to get run when events happen.
import plotlywrapper as pw
def callback(item):
chart = pw.line(range(item['value']))
plot.do_all(chart.dict)
We'll run this function in response to a dropdown event.
The passed object for this dropdown is a dictionary with two keys: "label" and "value".
To update the plot we call the do_all method.
15 / 50
Layout the App
16 / 50
Layout the App
We've chosen the components and de ned the functionality. Now we just need to connect events to
functions and lay out the widgets.
16 / 50
Layout the App
We've chosen the components and de ned the functionality. Now we just need to connect events to
functions and lay out the widgets.
from bowtie import command
@command
def build():
from bowtie import Layout
layout = Layout()
layout.add(plot)
layout.add_sidebar(ddown)
layout.subscribe(callback, ddown.on_change)
layout.build()
16 / 50
Layout the App
from bowtie import command
The command decorator turns this function into a command line interface.
@command
def build():
from bowtie import Layout
layout = Layout()
layout.add(plot)
layout.add_sidebar(ddown)
layout.subscribe(callback, ddown.on_change)
layout.build()
17 / 50
Layout the App
from bowtie import command
@command
def build():
from bowtie import Layout
layout = Layout()
These add* calls place widgets into our app.
layout.add(plot)
layout.add_sidebar(ddown)
layout.subscribe(callback, ddown.on_change)
layout.build()
18 / 50
Layout the App
from bowtie import command
@command
def build():
from bowtie import Layout
layout = Layout()
layout.add(plot)
layout.add_sidebar(ddown)
subscribe makes sure the callback gets run in response to the given event.
layout.subscribe(callback, ddown.on_change)
layout.build()
19 / 50
Layout the App
from bowtie import command
@command
def build():
from bowtie import Layout
layout = Layout(debug=True)
layout.add(plot)
layout.add_sidebar(ddown)
layout.subscribe(callback, ddown.on_change)
Finally, build compiles the app for us.
layout.build()
20 / 50
Build and Serve
21 / 50
Build and Serve
We're done writing the app, time to build and run it.
21 / 50
Build and Serve
We're done writing the app, time to build and run it.
The CLI we have gives us these commands:
Commands:
build Write the app, downloads the packages, and...
dev Recompile the app for development.
prod Recompile the app for production.
serve Serve the Bowtie app.
21 / 50
Build and Serve
We're done writing the app, time to build and run it.
The CLI we have gives us these commands:
Commands:
build Write the app, downloads the packages, and...
dev Recompile the app for development.
prod Recompile the app for production.
serve Serve the Bowtie app.
$ ./app.py build
21 / 50
Build and Serve
We're done writing the app, time to build and run it.
The CLI we have gives us these commands:
Commands:
build Write the app, downloads the packages, and...
dev Recompile the app for development.
prod Recompile the app for production.
serve Serve the Bowtie app.
$ ./app.py build
$ ./app.py serve
21 / 50
22 / 50
23 / 50
Rapid prototyping
24 / 50
Rapid prototyping
Set Layout(debug=True)! Enables live code reloading on write.
25 / 50
Rapid prototyping
Set Layout(debug=True)! Enables live code reloading on write.
Minimize builds by architecting app at the beginning.
25 / 50
Rapid prototyping
Set Layout(debug=True)! Enables live code reloading on write.
Minimize builds by architecting app at the beginning.
Use debuggers or prints to learn the payload.
def select(points):
one of the following:
print(points)
import ipdb; ipdb.set_trace()
import IPython; IPython.embed()
import wdb; wdb.set_trace()
25 / 50
Advanced Features
26 / 50
Listening to Plotly Events
27 / 50
Listening to Plotly Events
Plotly is a featureful Javascript charting library.
27 / 50
Listening to Plotly Events
Plotly is a featureful Javascript charting library.
It has several events and Bowtie exposes three event types: selection, click, and hover.
27 / 50
Listening to Plotly Events
Plotly is a featureful Javascript charting library.
It has several events and Bowtie exposes three event types: selection, click, and hover.
The data it returns is not well documented, but it's not too hard to gure out.
27 / 50
Subscribe to Multiple Events
28 / 50
Subscribe to Multiple Events
A common use-case is for a function to use the output from several widgets.
28 / 50
Subscribe to Multiple Events
A common use-case is for a function to use the output from several widgets.
Cumbersome to write individual callbacks for each event and get the other widgets' states.
def foo(a,b):
pass
def cb1(a):
b = b.get()
foo(a,b)
def cb2(b):
a = a.get()
foo(a,b)
28 / 50
Subscribe to Multiple Events
A common use-case is for a function to use the output from several widgets.
Cumbersome to write individual callbacks for each event and get the other widgets' states.
def foo(a,b):
pass
def cb1(a):
b = b.get()
foo(a,b)
def cb2(b):
a = a.get()
foo(a,b)
A better way is to subscribe callbacks to multiple events.
28 / 50
Subscribe to Multiple Events
A common use-case is for a function to use the output from several widgets.
Cumbersome to write individual callbacks for each event and get the other widgets' states.
def foo(a,b):
pass
def cb1(a):
b = b.get()
foo(a,b)
def cb2(b):
a = a.get()
foo(a,b)
A better way is to subscribe callbacks to multiple events.
def func(item1, item2, switch):
cool_stuff()
...
layout.subscribe(func, ddown1.on_select, ddown2.on_select, switch.on_switch)
28 / 50
Scheduling and Loading Events
29 / 50
Scheduling and Loading Events
Bowtie also de nes intrinsic event types.
29 / 50
Scheduling and Loading Events
Bowtie also de nes intrinsic event types.
Instruct a function to run when a user loads the page.
layout.load(func)
29 / 50
Scheduling and Loading Events
Bowtie also de nes intrinsic event types.
Instruct a function to run when a user loads the page.
layout.load(func)
Instruct a function to run periodically.
layout.schedule(5, func) # call func every 5 seconds
29 / 50
Storing data with the client
30 / 50
Storing data with the client
In some cases it's helpful to be able to store data with the client.
30 / 50
Storing data with the client
In some cases it's helpful to be able to store data with the client.
Could store it server-side, but that's more setup.
30 / 50
Storing data with the client
In some cases it's helpful to be able to store data with the client.
Could store it server-side, but that's more setup.
So we'll just send the data to the client and have them hold it.
30 / 50
Storing data with the client
In some cases it's helpful to be able to store data with the client.
Could store it server-side, but that's more setup.
So we'll just send the data to the client and have them hold it.
bowtie.cache gives a "key-value" store to save any python objects.
30 / 50
Storing data with the client
In some cases it's helpful to be able to store data with the client.
Could store it server-side, but that's more setup.
So we'll just send the data to the client and have them hold it.
bowtie.cache gives a "key-value" store to save any python objects.
Helpful to store results from expensive computations or client speci c data.
bowtie.cache.save(key, value)
value = bowtie.cache.load(key)
30 / 50
Progress Indicators
31 / 50
Progress Indicators
All visual widgets have an attached progress indicator.
31 / 50
Progress Indicators
All visual widgets have an attached progress indicator.
By default they are invisible so they don't get in your way.
31 / 50
Progress Indicators
All visual widgets have an attached progress indicator.
By default they are invisible so they don't get in your way.
Really helpful for long computations or slow I/O.
31 / 50
Progress Indicators
All visual widgets have an attached progress indicator.
By default they are invisible so they don't get in your way.
Really helpful for long computations or slow I/O.
Can also indicate error states.
31 / 50
Leverage CSS Grid
32 / 50
Leverage CSS Grid
New web standard to de ne grids on a page.
32 / 50
Leverage CSS Grid
New web standard to de ne grids on a page.
Bowtie uses this and makes a "pythonic" API.
32 / 50
Leverage CSS Grid
New web standard to de ne grids on a page.
Bowtie uses this and makes a "pythonic" API.
CSS Grid was just released onto major browsers.
32 / 50
Leverage CSS Grid
New web standard to de ne grids on a page.
Bowtie uses this and makes a "pythonic" API.
CSS Grid was just released onto major browsers.
Chrome >= 57, Firefox >= 52, Safari >= 10.1, Opera >= 44
32 / 50
Leverage CSS Grid
Layout class lets you specify how many rows and columns in the grid.
33 / 50
Leverage CSS Grid
Layout class lets you specify how many rows and columns in the grid.
call .add method and optionally specify which cells in the grid.
33 / 50
Leverage CSS Grid
Layout class lets you specify how many rows and columns in the grid.
call .add method and optionally specify which cells in the grid.
Widgets can span 1 or multiple cells.
33 / 50
Leverage CSS Grid
Layout class lets you specify how many rows and columns in the grid.
call .add method and optionally specify which cells in the grid.
Widgets can span 1 or multiple cells.
Rows and columns can be sized on pixels, percentage, and fraction of available space.
33 / 50
Authentication
34 / 50
Authentication
Flask makes it easy to support basic authentication.
34 / 50
Authentication
Flask makes it easy to support basic authentication.
Want to have a generic authentication solution.
34 / 50
Authentication
Flask makes it easy to support basic authentication.
Want to have a generic authentication solution.
I'm not a security expert so don't trust me.
34 / 50
35 / 50
Deploying
36 / 50
Deploying
37 / 50
Deploying
Heroku is an easy option.
37 / 50
Deploying
Heroku is an easy option.
Set Layout(debug=False)
37 / 50
Deploying
Heroku is an easy option.
Set Layout(debug=False)
Compile with production.
$ python app.py prod
Reduces JS bundle size by a factor of ~30 (from 30MB to 1MB).
37 / 50
Deploying
Heroku is an easy option.
Set Layout(debug=False)
Compile with production.
$ python app.py prod
Reduces JS bundle size by a factor of ~30 (from 30MB to 1MB).
Commit the following les
build/src/server.py
build/src/templates/index.html
build/src/static/bundle.js.gz
37 / 50
Tech Stack
38 / 50
Flask-SocketIO
39 / 50
Flask-SocketIO
Bowtie is built on Flask and Flask-SocketIO.
39 / 50
Flask-SocketIO
Bowtie is built on Flask and Flask-SocketIO.
Bowtie abstracts away most of Flask.
39 / 50
Flask-SocketIO
Bowtie is built on Flask and Flask-SocketIO.
Bowtie abstracts away most of Flask.
You can still bene t from the Flask ecosystem.
39 / 50
Flask-SocketIO
Bowtie is built on Flask and Flask-SocketIO.
Bowtie abstracts away most of Flask.
You can still bene t from the Flask ecosystem.
Kind of wish the user still touched Flask because it's a great API.
39 / 50
React
40 / 50
React
Nick Kridler (author of Pyxley) wrote about using React with Python.
40 / 50
React
Nick Kridler (author of Pyxley) wrote about using React with Python.
Frontend is written entirely in React.
40 / 50
React
Nick Kridler (author of Pyxley) wrote about using React with Python.
Frontend is written entirely in React.
Making a new widget means making a new React class that communicates via socket.io.
40 / 50
Talking through SocketIO
41 / 50
Talking through SocketIO
All communication between Python and Javascript is through SocketIO
41 / 50
Talking through SocketIO
All communication between Python and Javascript is through SocketIO
Unique events are created by combining the component id with the type of message.
41 / 50
Talking through SocketIO
All communication between Python and Javascript is through SocketIO
Unique events are created by combining the component id with the type of message.
For example: the event for updating Plotly is "{id}#all"
41 / 50
Talking through SocketIO
All communication between Python and Javascript is through SocketIO
Unique events are created by combining the component id with the type of message.
For example: the event for updating Plotly is "{id}#all"
Message payloads are encoded with msgpack to reduce payload size.
41 / 50
Javascript Tools
42 / 50
Javascript Tools
Yarn: for installing npm packages.
42 / 50
Javascript Tools
Yarn: for installing npm packages.
Webpack: for bundling the npm packages.
42 / 50
Javascript Tools
Yarn: for installing npm packages.
Webpack: for bundling the npm packages.
Leaky abstraction, but I don't want to turn bowtie into a node delivery device.
42 / 50
Future Work and Goals
43 / 50
Some things I don't like
44 / 50
Some things I don't like
You need to recompile your app to run it (when you make architectural changes) which takes a minute.
44 / 50
Some things I don't like
You need to recompile your app to run it (when you make architectural changes) which takes a minute.
Compared to some other tools, Bowtie is not as snappy.
44 / 50
Some things I don't like
You need to recompile your app to run it (when you make architectural changes) which takes a minute.
Compared to some other tools, Bowtie is not as snappy.
Perhaps too much magic happening behind the scenes, harder for users to change things and x issues.
44 / 50
User Experience Goals
45 / 50
User Experience Goals
The power to create as much interactivity as you want.
45 / 50
User Experience Goals
The power to create as much interactivity as you want.
Painless rapid prototyping
45 / 50
User Experience Goals
The power to create as much interactivity as you want.
Painless rapid prototyping
Be able to share with others
45 / 50
Non Goals
46 / 50
Non Goals
GUI for laying out widgets.
46 / 50
Non Goals
GUI for laying out widgets.
Generic web app builder (my focus is on data science applications).
46 / 50
Goals and Future Work
47 / 50
Goals and Future Work
Become Shiny!
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
Needs to be more robust, have better testing.
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
Needs to be more robust, have better testing.
Make it easier to scale and deploy.
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
Needs to be more robust, have better testing.
Make it easier to scale and deploy.
More charting libraries.
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
Needs to be more robust, have better testing.
Make it easier to scale and deploy.
More charting libraries.
More widgets.
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
Needs to be more robust, have better testing.
Make it easier to scale and deploy.
More charting libraries.
More widgets.
Make it look nicer?
47 / 50
Goals and Future Work
Become Shiny!
Okay, but seriously.
Needs to be more robust, have better testing.
Make it easier to scale and deploy.
More charting libraries.
More widgets.
Make it look nicer?
Jupyter integration (possible?)
47 / 50
My Real Goal
Whether Bowtie becomes the Shiny of Python or not, I simply
want to move the bar forward.
48 / 50
Thanks
To my Verdigris colleagues for feedback.
Danny Servén
Jared Kruzek
Martin Chang
Michael Roberts
To Je for letting me present.
49 / 50
Thanks
Github: github.com/jwkvam/bowtie
Slides: github.com/jwkvam/bowtie-talk
Docs: bowtie-py.rtfd.io
50 / 50

Mais conteúdo relacionado

Mais procurados

Desenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhoneDesenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhone
Tiago Oliveira
 

Mais procurados (20)

Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 
Power Of Zero
Power Of ZeroPower Of Zero
Power Of Zero
 
Intro To Spring Python
Intro To Spring PythonIntro To Spring Python
Intro To Spring Python
 
Ultimate Node.js countdown: the coolest Application Express examples
Ultimate Node.js countdown: the coolest Application Express examplesUltimate Node.js countdown: the coolest Application Express examples
Ultimate Node.js countdown: the coolest Application Express examples
 
Testing Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyTesting Ember Apps: Managing Dependency
Testing Ember Apps: Managing Dependency
 
Metrics-Driven Engineering
Metrics-Driven EngineeringMetrics-Driven Engineering
Metrics-Driven Engineering
 
Remote controlling Parrot AR drone with Vaadin & Spring Boot @ GWT.create
Remote controlling Parrot AR drone with Vaadin & Spring Boot @ GWT.createRemote controlling Parrot AR drone with Vaadin & Spring Boot @ GWT.create
Remote controlling Parrot AR drone with Vaadin & Spring Boot @ GWT.create
 
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
 
Just Married: Zend Framework and Doctrine
Just Married: Zend Framework and DoctrineJust Married: Zend Framework and Doctrine
Just Married: Zend Framework and Doctrine
 
Your code are my tests
Your code are my testsYour code are my tests
Your code are my tests
 
Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)
 
Towards the Cloud: Event-driven Architectures in PHP
Towards the Cloud: Event-driven Architectures in PHPTowards the Cloud: Event-driven Architectures in PHP
Towards the Cloud: Event-driven Architectures in PHP
 
JetBot basic motion
JetBot basic motionJetBot basic motion
JetBot basic motion
 
More android code puzzles
More android code puzzlesMore android code puzzles
More android code puzzles
 
Flutter hooks tutorial (part 1) flutter animation using hooks (use effect and...
Flutter hooks tutorial (part 1) flutter animation using hooks (use effect and...Flutter hooks tutorial (part 1) flutter animation using hooks (use effect and...
Flutter hooks tutorial (part 1) flutter animation using hooks (use effect and...
 
Ember testing internals with ember cli
Ember testing internals with ember cliEmber testing internals with ember cli
Ember testing internals with ember cli
 
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...Fullstack Conference -  Proxies before proxies: The hidden gems of Javascript...
Fullstack Conference - Proxies before proxies: The hidden gems of Javascript...
 
Web Performance Culture and Tools at Etsy
Web Performance Culture and Tools at EtsyWeb Performance Culture and Tools at Etsy
Web Performance Culture and Tools at Etsy
 
Desenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhoneDesenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhone
 
Ditching JQuery
Ditching JQueryDitching JQuery
Ditching JQuery
 

Semelhante a Bowtie: Interactive Dashboards

Behavior & Specification Driven Development in PHP - #OpenWest
Behavior & Specification Driven Development in PHP - #OpenWestBehavior & Specification Driven Development in PHP - #OpenWest
Behavior & Specification Driven Development in PHP - #OpenWest
Joshua Warren
 

Semelhante a Bowtie: Interactive Dashboards (20)

Incredible Machine with Pipelines and Generators
Incredible Machine with Pipelines and GeneratorsIncredible Machine with Pipelines and Generators
Incredible Machine with Pipelines and Generators
 
Demystifying Maven
Demystifying MavenDemystifying Maven
Demystifying Maven
 
React & The Art of Managing Complexity
React &  The Art of Managing ComplexityReact &  The Art of Managing Complexity
React & The Art of Managing Complexity
 
Behavior & Specification Driven Development in PHP - #OpenWest
Behavior & Specification Driven Development in PHP - #OpenWestBehavior & Specification Driven Development in PHP - #OpenWest
Behavior & Specification Driven Development in PHP - #OpenWest
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Rits Brown Bag - Salesforce Lightning
Rits Brown Bag - Salesforce LightningRits Brown Bag - Salesforce Lightning
Rits Brown Bag - Salesforce Lightning
 
Google Wave API: Now and Beyond
Google Wave API: Now and BeyondGoogle Wave API: Now and Beyond
Google Wave API: Now and Beyond
 
Using prime[31] to connect your unity game to azure mobile services
Using prime[31] to connect your unity game to azure mobile servicesUsing prime[31] to connect your unity game to azure mobile services
Using prime[31] to connect your unity game to azure mobile services
 
Shift Remote: Mobile - Devops-ify your life with Github Actions - Nicola Cort...
Shift Remote: Mobile - Devops-ify your life with Github Actions - Nicola Cort...Shift Remote: Mobile - Devops-ify your life with Github Actions - Nicola Cort...
Shift Remote: Mobile - Devops-ify your life with Github Actions - Nicola Cort...
 
Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!
 
Reactive programming with tracker
Reactive programming with trackerReactive programming with tracker
Reactive programming with tracker
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
Developer Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for BeginnersDeveloper Student Clubs NUK - Flutter for Beginners
Developer Student Clubs NUK - Flutter for Beginners
 
Understanding Framework Architecture using Eclipse
Understanding Framework Architecture using EclipseUnderstanding Framework Architecture using Eclipse
Understanding Framework Architecture using Eclipse
 
Scala Future & Promises
Scala Future & PromisesScala Future & Promises
Scala Future & Promises
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend Developers
 
React Native custom components
React Native custom componentsReact Native custom components
React Native custom components
 

Último

CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
amitlee9823
 
Al Barsha Escorts $#$ O565212860 $#$ Escort Service In Al Barsha
Al Barsha Escorts $#$ O565212860 $#$ Escort Service In Al BarshaAl Barsha Escorts $#$ O565212860 $#$ Escort Service In Al Barsha
Al Barsha Escorts $#$ O565212860 $#$ Escort Service In Al Barsha
AroojKhan71
 
Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...
Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...
Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...
amitlee9823
 
Probability Grade 10 Third Quarter Lessons
Probability Grade 10 Third Quarter LessonsProbability Grade 10 Third Quarter Lessons
Probability Grade 10 Third Quarter Lessons
JoseMangaJr1
 

Último (20)

ALSO dropshipping via API with DroFx.pptx
ALSO dropshipping via API with DroFx.pptxALSO dropshipping via API with DroFx.pptx
ALSO dropshipping via API with DroFx.pptx
 
Edukaciniai dropshipping via API with DroFx
Edukaciniai dropshipping via API with DroFxEdukaciniai dropshipping via API with DroFx
Edukaciniai dropshipping via API with DroFx
 
Mature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxMature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptx
 
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Saket (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Predicting Loan Approval: A Data Science Project
Predicting Loan Approval: A Data Science ProjectPredicting Loan Approval: A Data Science Project
Predicting Loan Approval: A Data Science Project
 
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort ServiceBDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
 
Cheap Rate Call girls Sarita Vihar Delhi 9205541914 shot 1500 night
Cheap Rate Call girls Sarita Vihar Delhi 9205541914 shot 1500 nightCheap Rate Call girls Sarita Vihar Delhi 9205541914 shot 1500 night
Cheap Rate Call girls Sarita Vihar Delhi 9205541914 shot 1500 night
 
Smarteg dropshipping via API with DroFx.pptx
Smarteg dropshipping via API with DroFx.pptxSmarteg dropshipping via API with DroFx.pptx
Smarteg dropshipping via API with DroFx.pptx
 
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
 
Invezz.com - Grow your wealth with trading signals
Invezz.com - Grow your wealth with trading signalsInvezz.com - Grow your wealth with trading signals
Invezz.com - Grow your wealth with trading signals
 
Carero dropshipping via API with DroFx.pptx
Carero dropshipping via API with DroFx.pptxCarero dropshipping via API with DroFx.pptx
Carero dropshipping via API with DroFx.pptx
 
Capstone Project on IBM Data Analytics Program
Capstone Project on IBM Data Analytics ProgramCapstone Project on IBM Data Analytics Program
Capstone Project on IBM Data Analytics Program
 
BabyOno dropshipping via API with DroFx.pptx
BabyOno dropshipping via API with DroFx.pptxBabyOno dropshipping via API with DroFx.pptx
BabyOno dropshipping via API with DroFx.pptx
 
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
 
Al Barsha Escorts $#$ O565212860 $#$ Escort Service In Al Barsha
Al Barsha Escorts $#$ O565212860 $#$ Escort Service In Al BarshaAl Barsha Escorts $#$ O565212860 $#$ Escort Service In Al Barsha
Al Barsha Escorts $#$ O565212860 $#$ Escort Service In Al Barsha
 
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
(NEHA) Call Girls Katra Call Now 8617697112 Katra Escorts 24x7
 
Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...
Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...
Vip Mumbai Call Girls Marol Naka Call On 9920725232 With Body to body massage...
 
Probability Grade 10 Third Quarter Lessons
Probability Grade 10 Third Quarter LessonsProbability Grade 10 Third Quarter Lessons
Probability Grade 10 Third Quarter Lessons
 
CebaBaby dropshipping via API with DroFX.pptx
CebaBaby dropshipping via API with DroFX.pptxCebaBaby dropshipping via API with DroFX.pptx
CebaBaby dropshipping via API with DroFX.pptx
 
Discover Why Less is More in B2B Research
Discover Why Less is More in B2B ResearchDiscover Why Less is More in B2B Research
Discover Why Less is More in B2B Research
 

Bowtie: Interactive Dashboards

  • 3. Who am I? 3 / 50
  • 4. Who am I? Computer Engineer turned "Data Scientist". 3 / 50
  • 5. Who am I? Computer Engineer turned "Data Scientist". Work at energy analytics startup, Verdigris Technologies. 3 / 50
  • 6. Who am I? Computer Engineer turned "Data Scientist". Work at energy analytics startup, Verdigris Technologies. Heavy Python user for 3-5 years. 3 / 50
  • 7. Who am I? Computer Engineer turned "Data Scientist". Work at energy analytics startup, Verdigris Technologies. Heavy Python user for 3-5 years. I'm not a frontend developer. 3 / 50
  • 11. Agenda Motivation A quick start Rapid prototyping tips 4 / 50
  • 12. Agenda Motivation A quick start Rapid prototyping tips Advanced features 4 / 50
  • 13. Agenda Motivation A quick start Rapid prototyping tips Advanced features How to deploy 4 / 50
  • 14. Agenda Motivation A quick start Rapid prototyping tips Advanced features How to deploy Tech stack 4 / 50
  • 15. Agenda Motivation A quick start Rapid prototyping tips Advanced features How to deploy Tech stack Future work and goals 4 / 50
  • 16. Agenda Motivation A quick start Rapid prototyping tips Advanced features How to deploy Tech stack Future work and goals Will not be discussing similar tools. 4 / 50
  • 18. Motivation Want to click on a chart and generate another chart. 5 / 50
  • 19. Motivation Want to click on a chart and generate another chart. 5 / 50
  • 21. Tool Survey Don't want to use R! 6 / 50
  • 22. Tool Survey Don't want to use R! Looked for solutions in Python. 6 / 50
  • 23. Tool Survey Don't want to use R! Looked for solutions in Python. Thought this should be easier. 6 / 50
  • 24. Tool Survey Don't want to use R! Looked for solutions in Python. Thought this should be easier. Thought it would be fun to write something. 6 / 50
  • 27. Initial Thoughts Plotly charts have lots of events: selection, click, and hover. 8 / 50
  • 28. Initial Thoughts Plotly charts have lots of events: selection, click, and hover. Just need to communicate between Python and JS in browser. 8 / 50
  • 29. Initial Thoughts Plotly charts have lots of events: selection, click, and hover. Just need to communicate between Python and JS in browser. Socket.io seems like it could do the trick. 8 / 50
  • 30. Initial Thoughts Plotly charts have lots of events: selection, click, and hover. Just need to communicate between Python and JS in browser. Socket.io seems like it could do the trick. That's good enough for a proof of concept. 8 / 50
  • 31. Fast forward a few months 9 / 50
  • 32. Your First Bowtie App 10 / 50
  • 33. Your First Bowtie App Each app has three parts 10 / 50
  • 34. Your First Bowtie App Each app has three parts Choose the components in your app. 10 / 50
  • 35. Your First Bowtie App Each app has three parts Choose the components in your app. Write the callbacks (in response to events). 10 / 50
  • 36. Your First Bowtie App Each app has three parts Choose the components in your app. Write the callbacks (in response to events). Layout the components and connect everything. 10 / 50
  • 37. First we need some prereqs 11 / 50
  • 38. First we need some prereqs Need Node to get us yarn and webpack. $ brew install node $ npm install -g webpack $ brew install yarn Sorry for the MacOS bias. 11 / 50
  • 39. First we need some prereqs Need Node to get us yarn and webpack. $ brew install node $ npm install -g webpack $ brew install yarn Sorry for the MacOS bias. Install Bowtie. $ pip install bowtie Works on Python 2 and 3 11 / 50
  • 42. Select the components These are the widgets that exist in your app. 13 / 50
  • 43. Select the components These are the widgets that exist in your app. Full list of components on readthedocs. 13 / 50
  • 44. Select the components These are the widgets that exist in your app. Full list of components on readthedocs. Split into two categories: visual widgets and controller widgets. 13 / 50
  • 45. Select the components These are the widgets that exist in your app. Full list of components on readthedocs. Split into two categories: visual widgets and controller widgets. Visual: Plotly, SVG (matplotlib), Tables 13 / 50
  • 46. Select the components These are the widgets that exist in your app. Full list of components on readthedocs. Split into two categories: visual widgets and controller widgets. Visual: Plotly, SVG (matplotlib), Tables Controllers: DatePickers, Dropdown, Text, Sliders, Toggle, and a Button. 13 / 50
  • 47. Select the components These are the widgets that exist in your app. Full list of components on readthedocs. Split into two categories: visual widgets and controller widgets. Visual: Plotly, SVG (matplotlib), Tables Controllers: DatePickers, Dropdown, Text, Sliders, Toggle, and a Button. from bowtie.visual import Plotly from bowtie.control import Dropdown plot = Plotly() ddown = Dropdown() 13 / 50
  • 48. What do these components do? 14 / 50
  • 49. What do these components do? Instructions for displaying itself in a webpage. 14 / 50
  • 50. What do these components do? Instructions for displaying itself in a webpage. Commands, pre xed with do_, to update the state of the widget. 14 / 50
  • 51. What do these components do? Instructions for displaying itself in a webpage. Commands, pre xed with do_, to update the state of the widget. Events, pre xed with on_, to run python in response to. 14 / 50
  • 52. What do these components do? Instructions for displaying itself in a webpage. Commands, pre xed with do_, to update the state of the widget. Events, pre xed with on_, to run python in response to. Getters, pre xed with get, gets the current states of the widget. 14 / 50
  • 53. What do these components do? Instructions for displaying itself in a webpage. Commands, pre xed with do_, to update the state of the widget. Events, pre xed with on_, to run python in response to. Getters, pre xed with get, gets the current states of the widget. For example: Dropdown docs. 14 / 50
  • 54. De ne the callbacks 15 / 50
  • 55. De ne the callbacks We'll de ne functions to get run when events happen. 15 / 50
  • 56. De ne the callbacks We'll de ne functions to get run when events happen. import plotlywrapper as pw def callback(item): chart = pw.line(range(item['value'])) plot.do_all(chart.dict) 15 / 50
  • 57. De ne the callbacks We'll de ne functions to get run when events happen. import plotlywrapper as pw def callback(item): chart = pw.line(range(item['value'])) plot.do_all(chart.dict) We'll run this function in response to a dropdown event. 15 / 50
  • 58. De ne the callbacks We'll de ne functions to get run when events happen. import plotlywrapper as pw def callback(item): chart = pw.line(range(item['value'])) plot.do_all(chart.dict) We'll run this function in response to a dropdown event. The passed object for this dropdown is a dictionary with two keys: "label" and "value". 15 / 50
  • 59. De ne the callbacks We'll de ne functions to get run when events happen. import plotlywrapper as pw def callback(item): chart = pw.line(range(item['value'])) plot.do_all(chart.dict) We'll run this function in response to a dropdown event. The passed object for this dropdown is a dictionary with two keys: "label" and "value". To update the plot we call the do_all method. 15 / 50
  • 61. Layout the App We've chosen the components and de ned the functionality. Now we just need to connect events to functions and lay out the widgets. 16 / 50
  • 62. Layout the App We've chosen the components and de ned the functionality. Now we just need to connect events to functions and lay out the widgets. from bowtie import command @command def build(): from bowtie import Layout layout = Layout() layout.add(plot) layout.add_sidebar(ddown) layout.subscribe(callback, ddown.on_change) layout.build() 16 / 50
  • 63. Layout the App from bowtie import command The command decorator turns this function into a command line interface. @command def build(): from bowtie import Layout layout = Layout() layout.add(plot) layout.add_sidebar(ddown) layout.subscribe(callback, ddown.on_change) layout.build() 17 / 50
  • 64. Layout the App from bowtie import command @command def build(): from bowtie import Layout layout = Layout() These add* calls place widgets into our app. layout.add(plot) layout.add_sidebar(ddown) layout.subscribe(callback, ddown.on_change) layout.build() 18 / 50
  • 65. Layout the App from bowtie import command @command def build(): from bowtie import Layout layout = Layout() layout.add(plot) layout.add_sidebar(ddown) subscribe makes sure the callback gets run in response to the given event. layout.subscribe(callback, ddown.on_change) layout.build() 19 / 50
  • 66. Layout the App from bowtie import command @command def build(): from bowtie import Layout layout = Layout(debug=True) layout.add(plot) layout.add_sidebar(ddown) layout.subscribe(callback, ddown.on_change) Finally, build compiles the app for us. layout.build() 20 / 50
  • 68. Build and Serve We're done writing the app, time to build and run it. 21 / 50
  • 69. Build and Serve We're done writing the app, time to build and run it. The CLI we have gives us these commands: Commands: build Write the app, downloads the packages, and... dev Recompile the app for development. prod Recompile the app for production. serve Serve the Bowtie app. 21 / 50
  • 70. Build and Serve We're done writing the app, time to build and run it. The CLI we have gives us these commands: Commands: build Write the app, downloads the packages, and... dev Recompile the app for development. prod Recompile the app for production. serve Serve the Bowtie app. $ ./app.py build 21 / 50
  • 71. Build and Serve We're done writing the app, time to build and run it. The CLI we have gives us these commands: Commands: build Write the app, downloads the packages, and... dev Recompile the app for development. prod Recompile the app for production. serve Serve the Bowtie app. $ ./app.py build $ ./app.py serve 21 / 50
  • 75. Rapid prototyping Set Layout(debug=True)! Enables live code reloading on write. 25 / 50
  • 76. Rapid prototyping Set Layout(debug=True)! Enables live code reloading on write. Minimize builds by architecting app at the beginning. 25 / 50
  • 77. Rapid prototyping Set Layout(debug=True)! Enables live code reloading on write. Minimize builds by architecting app at the beginning. Use debuggers or prints to learn the payload. def select(points): one of the following: print(points) import ipdb; ipdb.set_trace() import IPython; IPython.embed() import wdb; wdb.set_trace() 25 / 50
  • 79. Listening to Plotly Events 27 / 50
  • 80. Listening to Plotly Events Plotly is a featureful Javascript charting library. 27 / 50
  • 81. Listening to Plotly Events Plotly is a featureful Javascript charting library. It has several events and Bowtie exposes three event types: selection, click, and hover. 27 / 50
  • 82. Listening to Plotly Events Plotly is a featureful Javascript charting library. It has several events and Bowtie exposes three event types: selection, click, and hover. The data it returns is not well documented, but it's not too hard to gure out. 27 / 50
  • 83. Subscribe to Multiple Events 28 / 50
  • 84. Subscribe to Multiple Events A common use-case is for a function to use the output from several widgets. 28 / 50
  • 85. Subscribe to Multiple Events A common use-case is for a function to use the output from several widgets. Cumbersome to write individual callbacks for each event and get the other widgets' states. def foo(a,b): pass def cb1(a): b = b.get() foo(a,b) def cb2(b): a = a.get() foo(a,b) 28 / 50
  • 86. Subscribe to Multiple Events A common use-case is for a function to use the output from several widgets. Cumbersome to write individual callbacks for each event and get the other widgets' states. def foo(a,b): pass def cb1(a): b = b.get() foo(a,b) def cb2(b): a = a.get() foo(a,b) A better way is to subscribe callbacks to multiple events. 28 / 50
  • 87. Subscribe to Multiple Events A common use-case is for a function to use the output from several widgets. Cumbersome to write individual callbacks for each event and get the other widgets' states. def foo(a,b): pass def cb1(a): b = b.get() foo(a,b) def cb2(b): a = a.get() foo(a,b) A better way is to subscribe callbacks to multiple events. def func(item1, item2, switch): cool_stuff() ... layout.subscribe(func, ddown1.on_select, ddown2.on_select, switch.on_switch) 28 / 50
  • 88. Scheduling and Loading Events 29 / 50
  • 89. Scheduling and Loading Events Bowtie also de nes intrinsic event types. 29 / 50
  • 90. Scheduling and Loading Events Bowtie also de nes intrinsic event types. Instruct a function to run when a user loads the page. layout.load(func) 29 / 50
  • 91. Scheduling and Loading Events Bowtie also de nes intrinsic event types. Instruct a function to run when a user loads the page. layout.load(func) Instruct a function to run periodically. layout.schedule(5, func) # call func every 5 seconds 29 / 50
  • 92. Storing data with the client 30 / 50
  • 93. Storing data with the client In some cases it's helpful to be able to store data with the client. 30 / 50
  • 94. Storing data with the client In some cases it's helpful to be able to store data with the client. Could store it server-side, but that's more setup. 30 / 50
  • 95. Storing data with the client In some cases it's helpful to be able to store data with the client. Could store it server-side, but that's more setup. So we'll just send the data to the client and have them hold it. 30 / 50
  • 96. Storing data with the client In some cases it's helpful to be able to store data with the client. Could store it server-side, but that's more setup. So we'll just send the data to the client and have them hold it. bowtie.cache gives a "key-value" store to save any python objects. 30 / 50
  • 97. Storing data with the client In some cases it's helpful to be able to store data with the client. Could store it server-side, but that's more setup. So we'll just send the data to the client and have them hold it. bowtie.cache gives a "key-value" store to save any python objects. Helpful to store results from expensive computations or client speci c data. bowtie.cache.save(key, value) value = bowtie.cache.load(key) 30 / 50
  • 99. Progress Indicators All visual widgets have an attached progress indicator. 31 / 50
  • 100. Progress Indicators All visual widgets have an attached progress indicator. By default they are invisible so they don't get in your way. 31 / 50
  • 101. Progress Indicators All visual widgets have an attached progress indicator. By default they are invisible so they don't get in your way. Really helpful for long computations or slow I/O. 31 / 50
  • 102. Progress Indicators All visual widgets have an attached progress indicator. By default they are invisible so they don't get in your way. Really helpful for long computations or slow I/O. Can also indicate error states. 31 / 50
  • 104. Leverage CSS Grid New web standard to de ne grids on a page. 32 / 50
  • 105. Leverage CSS Grid New web standard to de ne grids on a page. Bowtie uses this and makes a "pythonic" API. 32 / 50
  • 106. Leverage CSS Grid New web standard to de ne grids on a page. Bowtie uses this and makes a "pythonic" API. CSS Grid was just released onto major browsers. 32 / 50
  • 107. Leverage CSS Grid New web standard to de ne grids on a page. Bowtie uses this and makes a "pythonic" API. CSS Grid was just released onto major browsers. Chrome >= 57, Firefox >= 52, Safari >= 10.1, Opera >= 44 32 / 50
  • 108. Leverage CSS Grid Layout class lets you specify how many rows and columns in the grid. 33 / 50
  • 109. Leverage CSS Grid Layout class lets you specify how many rows and columns in the grid. call .add method and optionally specify which cells in the grid. 33 / 50
  • 110. Leverage CSS Grid Layout class lets you specify how many rows and columns in the grid. call .add method and optionally specify which cells in the grid. Widgets can span 1 or multiple cells. 33 / 50
  • 111. Leverage CSS Grid Layout class lets you specify how many rows and columns in the grid. call .add method and optionally specify which cells in the grid. Widgets can span 1 or multiple cells. Rows and columns can be sized on pixels, percentage, and fraction of available space. 33 / 50
  • 113. Authentication Flask makes it easy to support basic authentication. 34 / 50
  • 114. Authentication Flask makes it easy to support basic authentication. Want to have a generic authentication solution. 34 / 50
  • 115. Authentication Flask makes it easy to support basic authentication. Want to have a generic authentication solution. I'm not a security expert so don't trust me. 34 / 50
  • 119. Deploying Heroku is an easy option. 37 / 50
  • 120. Deploying Heroku is an easy option. Set Layout(debug=False) 37 / 50
  • 121. Deploying Heroku is an easy option. Set Layout(debug=False) Compile with production. $ python app.py prod Reduces JS bundle size by a factor of ~30 (from 30MB to 1MB). 37 / 50
  • 122. Deploying Heroku is an easy option. Set Layout(debug=False) Compile with production. $ python app.py prod Reduces JS bundle size by a factor of ~30 (from 30MB to 1MB). Commit the following les build/src/server.py build/src/templates/index.html build/src/static/bundle.js.gz 37 / 50
  • 125. Flask-SocketIO Bowtie is built on Flask and Flask-SocketIO. 39 / 50
  • 126. Flask-SocketIO Bowtie is built on Flask and Flask-SocketIO. Bowtie abstracts away most of Flask. 39 / 50
  • 127. Flask-SocketIO Bowtie is built on Flask and Flask-SocketIO. Bowtie abstracts away most of Flask. You can still bene t from the Flask ecosystem. 39 / 50
  • 128. Flask-SocketIO Bowtie is built on Flask and Flask-SocketIO. Bowtie abstracts away most of Flask. You can still bene t from the Flask ecosystem. Kind of wish the user still touched Flask because it's a great API. 39 / 50
  • 130. React Nick Kridler (author of Pyxley) wrote about using React with Python. 40 / 50
  • 131. React Nick Kridler (author of Pyxley) wrote about using React with Python. Frontend is written entirely in React. 40 / 50
  • 132. React Nick Kridler (author of Pyxley) wrote about using React with Python. Frontend is written entirely in React. Making a new widget means making a new React class that communicates via socket.io. 40 / 50
  • 134. Talking through SocketIO All communication between Python and Javascript is through SocketIO 41 / 50
  • 135. Talking through SocketIO All communication between Python and Javascript is through SocketIO Unique events are created by combining the component id with the type of message. 41 / 50
  • 136. Talking through SocketIO All communication between Python and Javascript is through SocketIO Unique events are created by combining the component id with the type of message. For example: the event for updating Plotly is "{id}#all" 41 / 50
  • 137. Talking through SocketIO All communication between Python and Javascript is through SocketIO Unique events are created by combining the component id with the type of message. For example: the event for updating Plotly is "{id}#all" Message payloads are encoded with msgpack to reduce payload size. 41 / 50
  • 139. Javascript Tools Yarn: for installing npm packages. 42 / 50
  • 140. Javascript Tools Yarn: for installing npm packages. Webpack: for bundling the npm packages. 42 / 50
  • 141. Javascript Tools Yarn: for installing npm packages. Webpack: for bundling the npm packages. Leaky abstraction, but I don't want to turn bowtie into a node delivery device. 42 / 50
  • 142. Future Work and Goals 43 / 50
  • 143. Some things I don't like 44 / 50
  • 144. Some things I don't like You need to recompile your app to run it (when you make architectural changes) which takes a minute. 44 / 50
  • 145. Some things I don't like You need to recompile your app to run it (when you make architectural changes) which takes a minute. Compared to some other tools, Bowtie is not as snappy. 44 / 50
  • 146. Some things I don't like You need to recompile your app to run it (when you make architectural changes) which takes a minute. Compared to some other tools, Bowtie is not as snappy. Perhaps too much magic happening behind the scenes, harder for users to change things and x issues. 44 / 50
  • 148. User Experience Goals The power to create as much interactivity as you want. 45 / 50
  • 149. User Experience Goals The power to create as much interactivity as you want. Painless rapid prototyping 45 / 50
  • 150. User Experience Goals The power to create as much interactivity as you want. Painless rapid prototyping Be able to share with others 45 / 50
  • 152. Non Goals GUI for laying out widgets. 46 / 50
  • 153. Non Goals GUI for laying out widgets. Generic web app builder (my focus is on data science applications). 46 / 50
  • 154. Goals and Future Work 47 / 50
  • 155. Goals and Future Work Become Shiny! 47 / 50
  • 156. Goals and Future Work Become Shiny! Okay, but seriously. 47 / 50
  • 157. Goals and Future Work Become Shiny! Okay, but seriously. Needs to be more robust, have better testing. 47 / 50
  • 158. Goals and Future Work Become Shiny! Okay, but seriously. Needs to be more robust, have better testing. Make it easier to scale and deploy. 47 / 50
  • 159. Goals and Future Work Become Shiny! Okay, but seriously. Needs to be more robust, have better testing. Make it easier to scale and deploy. More charting libraries. 47 / 50
  • 160. Goals and Future Work Become Shiny! Okay, but seriously. Needs to be more robust, have better testing. Make it easier to scale and deploy. More charting libraries. More widgets. 47 / 50
  • 161. Goals and Future Work Become Shiny! Okay, but seriously. Needs to be more robust, have better testing. Make it easier to scale and deploy. More charting libraries. More widgets. Make it look nicer? 47 / 50
  • 162. Goals and Future Work Become Shiny! Okay, but seriously. Needs to be more robust, have better testing. Make it easier to scale and deploy. More charting libraries. More widgets. Make it look nicer? Jupyter integration (possible?) 47 / 50
  • 163. My Real Goal Whether Bowtie becomes the Shiny of Python or not, I simply want to move the bar forward. 48 / 50
  • 164. Thanks To my Verdigris colleagues for feedback. Danny Servén Jared Kruzek Martin Chang Michael Roberts To Je for letting me present. 49 / 50