Skip to content

Shape drawing doc #2407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 2, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## Dev version

### Updated

- Updated Plotly.js to version 1.54.0. The main feature of the Plotly.js is the
possibility to draw layout shapes, using custom dragmodes and corresponding
modebar buttons.

### Added

- The `hover_data` parameter of `px` functions can now be a dictionary. This
Expand Down
29 changes: 26 additions & 3 deletions doc/python/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ jupyter:
text_representation:
extension: .md
format_name: markdown
format_version: '1.1'
jupytext_version: 1.1.1
format_version: '1.2'
jupytext_version: 1.3.0
kernelspec:
display_name: Python 3
language: python
Expand All @@ -20,7 +20,7 @@ jupyter:
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
version: 3.7.0
version: 3.7.3
plotly:
description: How to set the configuration options of figures using the Plotly
Python graphing library.
Expand Down Expand Up @@ -236,6 +236,29 @@ fig.show(config={
})
```

### Add optional shape-drawing buttons to modebar

Some modebar buttons of Cartesian plots are optional and have to be added explictly, using the `modeBarButtonsToAdd` config attribute. These buttons are used for drawing or erasing shapes. See [the tutorial on shapes and shape drawing](python/shapes#drawing-shapes-on-cartesian-plots) for more details.

```python
import plotly.graph_objects as go
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x='petal_width', y='sepal_length', color='species')
fig.update_layout(
dragmode='drawopenpath',
newshape_line_color='cyan',
title_text='Draw a path to separate versicolor and virginica'
)
fig.show(config={'modeBarButtonsToAdd':['drawline',
'drawopenpath',
'drawclosedpath',
'drawcircle',
'drawrect',
'eraseshape'
]})
```

### Double-Click Delay
Sets the maximum delay between two consecutive clicks to be interpreted as a double-click in milliseconds. This is the time interval between first mousedown and second mouseup. The default timing is 300 ms (less than half a second).
This setting propagates to all on-subplot double clicks (except for `geo` and `mapbox`).
Expand Down
57 changes: 56 additions & 1 deletion doc/python/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.2'
jupytext_version: 1.3.2
jupytext_version: 1.3.0
kernelspec:
display_name: Python 3
language: python
Expand Down Expand Up @@ -305,5 +305,60 @@ fig.update_layout(
fig.show(config={'doubleClick': 'reset'})
```

### Annotating layout image with shapes

_introduced in plotly 4.7_

It can be useful to add shapes to a layout image, for highlighting an object, drawing bounding boxes as part of a machine learning training set, or identifying seeds for a segmentation algorithm.

In order to enable shape drawing, you need to
- define a dragmode corresponding to a drawing tool (`'drawline'`,`'drawopenpath'`, `'drawclosedpath'`, `'drawcircle'`, or `'drawrect'`)
- add modebar buttons corresponding to the drawing tools you wish to use.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link to the config doc here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!


The style of new shapes is specified by the `newshape` layout attribute. Shapes can be selected and modified after they have been drawn. More details and examples are given in the [tutorial on shapes](/python/shapes#drawing-shapes-on-cartesian-plots).

Drawing or modifying a shape triggers a `relayout` event, which [can be captured by a callback inside a Dash application](https://dash.plotly.com/interactive-graphing).

```python
import plotly.graph_objects as go
fig = go.Figure()
# Add image
img_width = 1600
img_height = 900
scale_factor = 0.5
fig.add_layout_image(
dict(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the dict here is redundant I'm pretty sure, as add_layout_image accepts these values as kwargs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!

x=0,
sizex=img_width,
y=0,
sizey=img_height,
xref="x",
yref="y",
opacity=1.0,
layer="below",
source="https://raw.githubusercontent.com/michaelbabyn/plot_data/master/bridge.jpg")
)
fig.update_xaxes(showgrid=False, range=(0, img_width))
fig.update_yaxes(showgrid=False, scaleanchor='x', range=(img_height, 0))
# Line shape added programatically
fig.add_shape(
type='line', xref='x', yref='y',
x0=650, x1=1080, y0=380, y1=180, line_color='cyan'
)
# Set dragmode and newshape properties; add modebar buttons
fig.update_layout(
dragmode='drawrect',
newshape=dict(line_color='cyan'),
title_text='Drag to add annotations - use modebar to change drawing tool'
)
fig.show(config={'modeBarButtonsToAdd':['drawline',
'drawopenpath',
'drawclosedpath',
'drawcircle',
'drawrect',
'eraseshape'
]})
```

#### Reference
See https://plotly.com/python/reference/#layout-images for more information and chart attribute options!
51 changes: 49 additions & 2 deletions doc/python/imshow.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.2'
jupytext_version: 1.3.1
jupytext_version: 1.3.0
kernelspec:
display_name: Python 3
language: python
Expand All @@ -20,7 +20,7 @@ jupyter:
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
version: 3.6.8
version: 3.7.3
plotly:
description: How to display image data in Python with Plotly.
display_as: scientific
Expand Down Expand Up @@ -260,6 +260,53 @@ imshow. See the [plotly and datashader tutorial](/python/datashader/) for
examples on how to use plotly and datashader.


### Annotating image traces with shapes

_introduced in plotly 4.7_

It can be useful to add shapes to an image trace, for highlighting an object, drawing bounding boxes as part of a machine learning training set, or identifying seeds for a segmentation algorithm.

In order to enable shape drawing, you need to
- define a dragmode corresponding to a drawing tool (`'drawline'`,`'drawopenpath'`, `'drawclosedpath'`, `'drawcircle'`, or `'drawrect'`)
- add modebar buttons corresponding to the drawing tools you wish to use.

The style of new shapes is specified by the `newshape` layout attribute. Shapes can be selected and modified after they have been drawn. More details and examples are given in the [tutorial on shapes](/python/shapes#drawing-shapes-on-cartesian-plots).

Drawing or modifying a shape triggers a `relayout` event, which [can be captured by a callback inside a Dash application](https://dash.plotly.com/interactive-graphing).

```python
import plotly.express as px
from skimage import data
img = data.chelsea()
fig = px.imshow(img)
fig.add_annotation(
x=0.5,
y=0.9,
text="Drag and draw annotations",
xref="paper",
yref="paper",
showarrow=False,
font_size=20, font_color='cyan')
# Shape defined programatically
fig.add_shape(
type='rect',
x0=230, x1=290, y0=230, y1=280,
xref='x', yref='y',
line_color='cyan'
)
# Define dragmode, newshape parameters, amd add modebar buttons
fig.update_layout(
dragmode='drawrect',
newshape=dict(line_color='cyan'))
fig.show(config={'modeBarButtonsToAdd':['drawline',
'drawopenpath',
'drawclosedpath',
'drawcircle',
'drawrect',
'eraseshape'
]})
```

#### Reference
See https://plotly.com/python/reference/#image for more information and chart attribute options!

86 changes: 85 additions & 1 deletion doc/python/shapes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jupyter:
extension: .md
format_name: markdown
format_version: '1.2'
jupytext_version: 1.3.2
jupytext_version: 1.3.0
kernelspec:
display_name: Python 3
language: python
Expand Down Expand Up @@ -716,5 +716,89 @@ fig.update_layout(
fig.show()
```

### Drawing shapes on Cartesian plots

_introduced in plotly 4.7_

You can create layout shapes programatically, but you can also draw shapes manually by setting the `dragmode` to one of the shape-drawing modes: `'drawline'`,`'drawopenpath'`, `'drawclosedpath'`, `'drawcircle'`, or `'drawrect'`. If you need to switch between different shape-drawing or other dragmodes (panning, selecting, etc.), modebar buttons can be added in the `config` to select the dragmode.

This shape-drawing feature is particularly interesting for annotating graphs, in particular [image traces](/python/imshow) or [layout images](/python/images).

Once you have drawn shapes, you can select and modify an existing shape by clicking on its boundary (note the arrow pointer). Its fillcolor turns to pink to highlight the activated shape and then you can
- drag and resize it for lines, rectangles and circles/ellipses
- drag and move individual vertices for closed paths
- move individual vertices for open paths.

An activated shape is deleted by cliking on the `eraseshape` button.

Drawing or modifying a shape triggers a `relayout` event, which [can be captured by a callback inside a Dash application](https://dash.plotly.com/interactive-graphing).

```python
import plotly.graph_objects as go
fig = go.Figure()
text="Click and drag here <br> to draw a rectangle <br><br> or select another shape <br>in the modebar"
fig.add_annotation(
x=0.5,
y=0.5,
text=text,
xref="paper",
yref="paper",
showarrow=False,
font_size=20
)
# shape defined programatically
fig.add_shape(editable=True,
x0=-1, x1=0, y0=2, y1=3,
xref='x1', yref='y1')
# define dragmode and add modebar buttons
fig.update_layout(dragmode='drawrect')
fig.show(config={'modeBarButtonsToAdd':['drawline',
'drawopenpath',
'drawclosedpath',
'drawcircle',
'drawrect',
'eraseshape'
]})
```

### Style of user-drawn shapes

The layout `newshape` attribute controls the visual appearance of new shapes drawn by the user. `newshape` attributes have the same names as layout shapes.

```python
import plotly.graph_objects as go
fig = go.Figure()
text="Click and drag<br> to draw a rectangle <br><br> or select another shape <br>in the modebar"
fig.add_annotation(
x=0.5,
y=0.5,
text=text,
xref="paper",
yref="paper",
showarrow=False,
font_size=20
)
# shape defined programatically
fig.add_shape(line_color='yellow',
fillcolor='turquoise',
opacity=0.8,
editable=True,
x0=0, x1=1, y0=2, y1=3,
xref='x1', yref='y1'
)
fig.update_layout(dragmode='drawrect',
# style of new shapes
newshape=dict(line_color='yellow',
fillcolor='turquoise',
opacity=0.8))
fig.show(config={'modeBarButtonsToAdd':['drawline',
'drawopenpath',
'drawclosedpath',
'drawcircle',
'drawrect',
'eraseshape'
]})
```

### Reference
See https://plotly.com/python/reference/#layout-shapes for more information and chart attribute options!