Skip to content

Commit dbbffe3

Browse files
committed
rough outline of migration guide
1 parent cc4f53c commit dbbffe3

File tree

2 files changed

+265
-110
lines changed

2 files changed

+265
-110
lines changed

migration-guide.md

Lines changed: 217 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,124 @@
11
# Migration to Plotly 3.0.0
2+
There are many new and great features in this branch including deeper Jupyter integration, deeper figure validation, improved performance, and more. To get started right away with Plotly, check out the [tutorial](#getting-started) below.
23

3-
Plotly 3 introduces huge enhancements to the `plotly.py` visualization library from tab completion for properties in the Jupyter to a tighter validation detection to catch unknown figure errors, plotly 3 provides better workflow for Plotly users.
4-
4+
To install and enable with Jupyter, run:
5+
```
6+
pip install plotly==3.0.0rc9
7+
pip install ipywidgets # only necessary for Jupyter Notebook environments
8+
```
59

6-
# Added
7-
[asd](#foo)
10+
In addition, to add JupyterLab support run the following commands:
811

12+
```
13+
pip install jupyterlab
14+
jupyter labextension install @jupyter-widgets/jupyterlab-manager # install the Jupyter widgets extension
15+
jupyter labextension install plotlywidget
16+
```
917

10-
# What's Added?
18+
## 3.0.0rc9 [08-06-2018]
19+
### Added
20+
- update traces interactively
1121
- Traces can be added and updated interactively by simply assigning to properties
12-
1322
- The full Traces and Layout API is generated from the plotly schema to provide a great experience for interactive use in the notebook
23+
- Jupyter friendly docstrings
24+
- Jupyter friendly docstrings on constructor params and properties
25+
- Support for setting array properties as numpy arrays. When numpy arrays are used, ipywidgets binary serialization protocol is used to avoid converting these to JSON strings.
26+
- Context manager API for animation
27+
- Programmatic export of figures to static SVG images (and PNG and PDF with cairosvg installed).
1428

15-
- Data validation covering the full API with clear, informative error messages
29+
### Removed
30+
- We have removed `.to_string`, `.strip_style`, `.get_data`, `.validate` and `.to_dataframe` methods from `plotly.graph_objs` objects. For example run `dir(plotly.graph_objs.Scatter)` to get all the (magic) methods of the Scatter class.
1631

1732

33+
### Changed
34+
- Improved data validation covering the full API with clear, informative error messages. This means that incorrect properties and/or values now always raise a `ValueError` with a description of the error, the invalid property, and the avaialble properties on the level that it was placed in the graph object. Eg. `go.Scatter(foo=123)` raises a validation error. See https://plot.ly/python/reference/ for a reference to all valid properties and values in the Python API.
1835

19-
- Jupyter friendly docstrings on constructor params and properties
36+
- graph objects are not `dict`s anymore. Running a cell of a graph object prints out a dict-style representation of the object:
2037

21-
- Support for setting array properties as numpy arrays. When numpy arrays are used, ipywidgets binary serialization protocol is used to avoid converting these to JSON strings.
38+
Eg. `plotly.graph_objs.Scatter()` prints
2239

23-
- Context manager API for animation
40+
```
41+
Scatter(**{
42+
'type': 'scatter'
43+
})
44+
```
2445

25-
- Programmatic export of figures to static SVG images (and PNG and PDF with cairosvg installed).
46+
- plotly objects now have a `.to_plotly_json` method that converts the object to a dict:
47+
48+
Eg. `go.Scatter().to_plotly_json()` returns `{'type': 'scatter'}`
49+
50+
51+
52+
### Deprecated
53+
- all graph objects must now be written using their full path. For example if one wants to customize the marker param in a scatter object, write `plotly.graph_objs.scatter.Marker` instead of `plotly.graph_objs.Marker`. If the marker object lives in a `plotly.graph_objs.Scatter()` object then a deprecated message will appear. Similarly
54+
55+
```
56+
import plotly.graph_objs as go
57+
go.Scatter(
58+
x=[0],
59+
y=[0],
60+
marker=go.Marker(
61+
color='rgb(255,45,15)'
62+
)
63+
)
64+
```
65+
66+
produces a deprecation warning but
67+
68+
```
69+
import plotly.graph_objs as go
70+
go.Scatter(
71+
x=[0],
72+
y=[0],
73+
marker=go.scatter.Marker(
74+
color='rgb(255,45,15)'
75+
)
76+
)
77+
```
78+
79+
does not.
80+
81+
- `go.Data()` is deprecated. Use a list or array `[]` instead.
82+
83+
84+
85+
# Getting Started
86+
#### Installation
87+
To install and enable with Jupyter, run:
88+
```
89+
pip install plotly==3.0.0rc9
90+
pip install ipywidgets # only necessary for Jupyter Notebook environments
91+
```
92+
93+
In addition, to add JupyterLab support run the following commands:
94+
95+
```
96+
pip install jupyterlab
97+
jupyter labextension install @jupyter-widgets/jupyterlab-manager # install the Jupyter widgets extension
98+
jupyter labextension install plotlywidget
99+
```
100+
101+
## Overview
102+
```
103+
# ipyplotly
104+
from plotly.graph_objs import FigureWidget
105+
from plotly.callbacks import Points, InputDeviceState
106+
107+
# pandas
108+
import pandas as pd
109+
110+
# numpy
111+
import numpy as np
112+
113+
# scikit learn
114+
from sklearn import datasets
26115
116+
# ipywidgets
117+
from ipywidgets import HBox, VBox, Button
118+
119+
# functools
120+
from functools import partial
121+
```
27122

28123
```
29124
# Load iris dataset
@@ -34,45 +129,38 @@ iris_class = iris_data.target + 1
34129
iris_df.head()
35130
```
36131

37-
| | sepal_length | sepal_width | petal_length | petal_width|
38-
| --- | --- | --- | --- |
39-
| 0 | 5.1 | 3.5 | 1.4 | 0.2 |
40-
| 1 | 4.9 | 3.0 | 1.4 | 0.2 |
41-
| 2 | 4.7 | 3.2 | 1.3 | 0.2 |
42-
| 3 | 4.6 | 3.1 | 1.5 | 0.2 |
43-
| 4 | 5.0 | 3.6 | 1.4 | 0.2 |
44-
45-
46-
## Create and display an empty FigureWidget
132+
#### Create and display an empty FigureWidget
47133
A FigureWidget behaves almost identically to a Figure but it is also an ipywidget that can be displayed directly in the notebook without calling `iplot`
48-
49134
```
50135
f1 = FigureWidget()
51136
f1
52137
```
53138

54-
## Tab completion
139+
#### Tab completion
55140
Entering ``f1.add_<tab>`` displays add methods for all of the supported trace types
141+
```
142+
# f1.add_
143+
```
56144

57145
Entering ``f1.add_scatter(<tab>)`` displays the names of all of the top-level properties for the scatter trace type
58146

59147
Entering ``f1.add_scatter(<shift+tab>)`` displays the signature pop-up. Expanding this pop-up reveals the method doc string which contains the descriptions of all of the top level properties
60148

61149
```
62-
# f1.add_
63-
# f1.add_scatter
150+
# f1.add_scatter(
64151
```
65152

66-
## Add scatter trace
153+
#### Add scatter trace
67154
```
68155
scatt1 = f1.add_scatter(x=iris_df.sepal_length, y=iris_df.petal_width)
69156
```
70157

71-
change the params
72158
```
73-
# Set marker
159+
# That's not what we wanted, change the mode to 'markers'
74160
scatt1.mode = 'markers'
161+
# Set size to 8
75162
scatt1.marker.size = 8
163+
# Color markers by iris class
76164
scatt1.marker.color = iris_class
77165
78166
# Change colorscale
@@ -89,7 +177,6 @@ scatt1.marker.colorbar.ticks = 'outside'
89177
scatt1.marker.colorbar.tickvals = [1, 2, 3]
90178
scatt1.marker.colorbar.ticktext = iris_data.target_names.tolist()
91179
92-
93180
# Set colorscale title
94181
scatt1.marker.colorbar.title = 'Species'
95182
scatt1.marker.colorbar.titlefont.size = 16
@@ -103,60 +190,125 @@ f1.layout.yaxis.title = 'petal_width'
103190
scatt1.text = iris_data.target_names[iris_data.target]
104191
scatt1.hoverinfo = 'text+x+y'
105192
f1.layout.hovermode = 'closest'
106-
107-
f1
108193
```
109194

195+
#### Animate marker size change
196+
```
197+
# Set marker size based on petal_length
198+
with f1.batch_animate(duration=1000):
199+
scatt1.marker.size = np.sqrt(iris_df.petal_length.values * 50)
110200
111-
## What have we Changed?
112-
- go.Figure() is not a dict
113-
- widgets in jupyter
201+
# Restore constant marker size
202+
with f1.batch_animate(duration=1000):
203+
scatt1.marker.size = 8
204+
```
114205

206+
#### Set drag mode property callback
207+
Make points more transparent when `dragmode` is `zoom`
115208
```
116-
import plotly.graph_objs as go
117-
scatter = go.Scatter()
209+
def set_opacity(marker, layout, dragmode):
210+
if dragmode == 'zoom':
211+
marker.opacity = 0.5
212+
else:
213+
marker.opacity = 1.0
214+
f1.layout.on_change(partial(set_opacity, scatt1.marker), 'dragmode')
118215
```
119216

217+
#### Configure colorscale for brushing
218+
```
219+
scatt1.marker.colorbar = None
220+
scatt1.marker.colorscale = [[0, 'lightgray'], [0.5, 'lightgray'], [0.5, 'red'], [1, 'red']]
221+
scatt1.marker.cmin = -0.5
222+
scatt1.marker.cmax = 1.5
223+
scatt1.marker.colorbar.ticks = 'outside'
224+
scatt1.marker.colorbar.tickvals = [0, 1]
225+
scatt1.marker.colorbar.ticktext = ['unselected', 'selected']
120226
121-
# What have we Removed?
122-
We have removed the following methods from the `plotly.graph_objs` plotly objects:
123-
- `.to_string`
124-
- `.strip_style`
125-
- `.get_data`
126-
- `.validate`
127-
- `.to_dataframe`
227+
# Reset colors to zeros (unselected)
228+
scatt1.marker.color = np.zeros(iris_class.size)
229+
selected = np.zeros(iris_class.size)
230+
```
128231

129-
# What is Depreciated?
232+
#### Configure brushing callback
233+
```
234+
# Assigning these variables here is not required. But doing so tricks Jupyter into
235+
# providing property tab completion on the parameters to the brush function below
236+
trace, points, state = scatt1, Points(), InputDeviceState()
130237
131-
- Plotly Objects form a tree hierarchy. For instance we have `go.Scatter` and the nested attribute `Marker` lives under scatter at `go.Scatter.Marker`. Now params that live a few nodes down the tree under a plotly class must be referenced in the full path.
238+
def brush(trace, points, state):
239+
inds = np.array(points.point_inds)
240+
if inds.size:
241+
selected[inds] = 1
242+
trace.marker.color = selected
132243
133-
Example:
134-
```
135-
fig = go.Figure(
136-
data=[
137-
go.Scatter(
138-
go.Scatter.Marker(
139-
symbol=0,
140-
),
141-
x=[1,2,3],
142-
y=[1,2,3],
143-
)
144-
]
145-
)
244+
scatt1.on_selected(brush)
146245
```
147246

148-
`go.Data` is depreciated:
149-
150-
Instead of
247+
Now box or lasso select points on the figure and see them turn red
151248

152249
```
153-
go.Data([])
250+
# Reset brush
251+
selected = np.zeros(iris_class.size)
252+
scatt1.marker.color = selected
154253
```
155254

156-
drop the go.Data and use a `list` instead:
255+
#### Create second plot with different features
256+
```
257+
f2 = FigureWidget(data=[{'type': 'scatter',
258+
'x': iris_df.petal_length,
259+
'y': iris_df.sepal_width,
260+
'mode': 'markers'}])
261+
f2
262+
```
157263

158264
```
159-
[]
265+
# Set axis titles
266+
f2.layout.xaxis.title = 'petal_length'
267+
f2.layout.yaxis.title = 'sepal_width'
268+
269+
# Grab trace reference
270+
scatt2 = f2.data[0]
271+
272+
# Set marker styles / colorbars to match between figures
273+
scatt2.marker = scatt1.marker
274+
275+
# Configure brush on both plots to update both plots
276+
def brush(trace, points, state):
277+
inds = np.array(points.point_inds)
278+
if inds.size:
279+
selected = scatt1.marker.color.copy()
280+
selected[inds] = 1
281+
scatt1.marker.color = selected
282+
scatt2.marker.color = selected
283+
284+
scatt1.on_selected(brush)
285+
scatt2.on_selected(brush)
286+
287+
f2.layout.on_change(partial(set_opacity, scatt2.marker), 'dragmode')
288+
289+
# Reset brush
290+
def reset_brush(btn):
291+
selected = np.zeros(iris_class.size)
292+
scatt1.marker.color = selected
293+
scatt2.marker.color = selected
294+
295+
# Create reset button
296+
button = Button(description="clear")
297+
button.on_click(reset_brush)
298+
299+
# Hide colorbar for figure 1
300+
scatt1.marker.showscale = False
301+
302+
# Set dragmode to lasso for both plots
303+
f1.layout.dragmode = 'lasso'
304+
f2.layout.dragmode = 'lasso'
305+
306+
# Display two figures and the reset button
307+
f1.layout.width = 500
308+
f2.layout.width = 500
309+
310+
VBox([HBox([f1, f2]), button])
160311
```
161312

162-
# foo
313+
#### Save figure 2 to a svg image in the exports directory
314+
f2.save_image('exports/f2.svg')

0 commit comments

Comments
 (0)