Skip to content

Commit e4c7f72

Browse files
Merge pull request plotly#2407 from plotly/shape-drawing-doc
Shape drawing doc
2 parents 3c1a7d1 + 0825d28 commit e4c7f72

File tree

5 files changed

+222
-6
lines changed

5 files changed

+222
-6
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## Dev version
66

7+
### Updated
8+
9+
- Updated Plotly.js to version 1.54.0. The main feature of the Plotly.js is the
10+
possibility to draw layout shapes, using custom dragmodes and corresponding
11+
modebar buttons.
12+
713
### Added
814

915
- The `hover_data` parameter of `px` functions can now be a dictionary. This

doc/python/configuration-options.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ jupyter:
55
text_representation:
66
extension: .md
77
format_name: markdown
8-
format_version: '1.1'
9-
jupytext_version: 1.1.1
8+
format_version: '1.2'
9+
jupytext_version: 1.3.0
1010
kernelspec:
1111
display_name: Python 3
1212
language: python
@@ -20,7 +20,7 @@ jupyter:
2020
name: python
2121
nbconvert_exporter: python
2222
pygments_lexer: ipython3
23-
version: 3.7.0
23+
version: 3.7.3
2424
plotly:
2525
description: How to set the configuration options of figures using the Plotly
2626
Python graphing library.
@@ -236,6 +236,29 @@ fig.show(config={
236236
})
237237
```
238238

239+
### Add optional shape-drawing buttons to modebar
240+
241+
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.
242+
243+
```python
244+
import plotly.graph_objects as go
245+
import plotly.express as px
246+
df = px.data.iris()
247+
fig = px.scatter(df, x='petal_width', y='sepal_length', color='species')
248+
fig.update_layout(
249+
dragmode='drawopenpath',
250+
newshape_line_color='cyan',
251+
title_text='Draw a path to separate versicolor and virginica'
252+
)
253+
fig.show(config={'modeBarButtonsToAdd':['drawline',
254+
'drawopenpath',
255+
'drawclosedpath',
256+
'drawcircle',
257+
'drawrect',
258+
'eraseshape'
259+
]})
260+
```
261+
239262
### Double-Click Delay
240263
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).
241264
This setting propagates to all on-subplot double clicks (except for `geo` and `mapbox`).

doc/python/images.md

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jupyter:
66
extension: .md
77
format_name: markdown
88
format_version: '1.2'
9-
jupytext_version: 1.3.2
9+
jupytext_version: 1.3.0
1010
kernelspec:
1111
display_name: Python 3
1212
language: python
@@ -305,5 +305,59 @@ fig.update_layout(
305305
fig.show(config={'doubleClick': 'reset'})
306306
```
307307

308+
### Annotating layout image with shapes
309+
310+
_introduced in plotly 4.7_
311+
312+
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.
313+
314+
In order to enable shape drawing, you need to
315+
- define a dragmode corresponding to a drawing tool (`'drawline'`,`'drawopenpath'`, `'drawclosedpath'`, `'drawcircle'`, or `'drawrect'`)
316+
- add [modebar buttons](/python/configuration-options#add-optional-shapedrawing-buttons-to-modebar) corresponding to the drawing tools you wish to use.
317+
318+
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).
319+
320+
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).
321+
322+
```python
323+
import plotly.graph_objects as go
324+
fig = go.Figure()
325+
# Add image
326+
img_width = 1600
327+
img_height = 900
328+
scale_factor = 0.5
329+
fig.add_layout_image(
330+
x=0,
331+
sizex=img_width,
332+
y=0,
333+
sizey=img_height,
334+
xref="x",
335+
yref="y",
336+
opacity=1.0,
337+
layer="below",
338+
source="https://raw.githubusercontent.com/michaelbabyn/plot_data/master/bridge.jpg"
339+
)
340+
fig.update_xaxes(showgrid=False, range=(0, img_width))
341+
fig.update_yaxes(showgrid=False, scaleanchor='x', range=(img_height, 0))
342+
# Line shape added programatically
343+
fig.add_shape(
344+
type='line', xref='x', yref='y',
345+
x0=650, x1=1080, y0=380, y1=180, line_color='cyan'
346+
)
347+
# Set dragmode and newshape properties; add modebar buttons
348+
fig.update_layout(
349+
dragmode='drawrect',
350+
newshape=dict(line_color='cyan'),
351+
title_text='Drag to add annotations - use modebar to change drawing tool'
352+
)
353+
fig.show(config={'modeBarButtonsToAdd':['drawline',
354+
'drawopenpath',
355+
'drawclosedpath',
356+
'drawcircle',
357+
'drawrect',
358+
'eraseshape'
359+
]})
360+
```
361+
308362
#### Reference
309363
See https://plotly.com/python/reference/#layout-images for more information and chart attribute options!

doc/python/imshow.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jupyter:
2020
name: python
2121
nbconvert_exporter: python
2222
pygments_lexer: ipython3
23-
version: 3.7.7
23+
version: 3.7.3
2424
plotly:
2525
description: How to display image data in Python with Plotly.
2626
display_as: scientific
@@ -260,6 +260,53 @@ imshow. See the [plotly and datashader tutorial](/python/datashader/) for
260260
examples on how to use plotly and datashader.
261261

262262

263+
### Annotating image traces with shapes
264+
265+
_introduced in plotly 4.7_
266+
267+
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.
268+
269+
In order to enable shape drawing, you need to
270+
- define a dragmode corresponding to a drawing tool (`'drawline'`,`'drawopenpath'`, `'drawclosedpath'`, `'drawcircle'`, or `'drawrect'`)
271+
- add modebar buttons corresponding to the drawing tools you wish to use.
272+
273+
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).
274+
275+
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).
276+
277+
```python
278+
import plotly.express as px
279+
from skimage import data
280+
img = data.chelsea()
281+
fig = px.imshow(img)
282+
fig.add_annotation(
283+
x=0.5,
284+
y=0.9,
285+
text="Drag and draw annotations",
286+
xref="paper",
287+
yref="paper",
288+
showarrow=False,
289+
font_size=20, font_color='cyan')
290+
# Shape defined programatically
291+
fig.add_shape(
292+
type='rect',
293+
x0=230, x1=290, y0=230, y1=280,
294+
xref='x', yref='y',
295+
line_color='cyan'
296+
)
297+
# Define dragmode, newshape parameters, amd add modebar buttons
298+
fig.update_layout(
299+
dragmode='drawrect',
300+
newshape=dict(line_color='cyan'))
301+
fig.show(config={'modeBarButtonsToAdd':['drawline',
302+
'drawopenpath',
303+
'drawclosedpath',
304+
'drawcircle',
305+
'drawrect',
306+
'eraseshape'
307+
]})
308+
```
309+
263310
#### Reference
264311
See https://plotly.com/python/reference/#image for more information and chart attribute options!
265312

doc/python/shapes.md

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jupyter:
66
extension: .md
77
format_name: markdown
88
format_version: '1.2'
9-
jupytext_version: 1.3.2
9+
jupytext_version: 1.3.0
1010
kernelspec:
1111
display_name: Python 3
1212
language: python
@@ -716,5 +716,91 @@ fig.update_layout(
716716
fig.show()
717717
```
718718

719+
### Drawing shapes on Cartesian plots
720+
721+
_introduced in plotly 4.7_
722+
723+
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](/python/configuration-options#add-optional-shapedrawing-buttons-to-modebar) in the `config` to select the dragmode. If you switch to a different dragmode such as pan or zoom, you will need to select the drawing tool in the modebar to go back to shape drawing.
724+
725+
This shape-drawing feature is particularly interesting for annotating graphs, in particular [image traces](/python/imshow) or [layout images](/python/images).
726+
727+
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
728+
- drag and resize it for lines, rectangles and circles/ellipses
729+
- drag and move individual vertices for closed paths
730+
- move individual vertices for open paths.
731+
732+
An activated shape is deleted by cliking on the `eraseshape` button.
733+
734+
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).
735+
736+
```python
737+
import plotly.graph_objects as go
738+
fig = go.Figure()
739+
text="Click and drag here <br> to draw a rectangle <br><br> or select another shape <br>in the modebar"
740+
fig.add_annotation(
741+
x=0.5,
742+
y=0.5,
743+
text=text,
744+
xref="paper",
745+
yref="paper",
746+
showarrow=False,
747+
font_size=20
748+
)
749+
# shape defined programatically
750+
fig.add_shape(editable=True,
751+
x0=-1, x1=0, y0=2, y1=3,
752+
xref='x1', yref='y1')
753+
# define dragmode and add modebar buttons
754+
fig.update_layout(dragmode='drawrect')
755+
fig.show(config={'modeBarButtonsToAdd':['drawline',
756+
'drawopenpath',
757+
'drawclosedpath',
758+
'drawcircle',
759+
'drawrect',
760+
'eraseshape'
761+
]})
762+
```
763+
764+
### Style of user-drawn shapes
765+
766+
The layout `newshape` attribute controls the visual appearance of new shapes drawn by the user. `newshape` attributes have the same names as layout shapes.
767+
768+
_Note on shape opacity_: having a new shape's opacity > 0.5 makes it possible to activate a shape by clicking inside the shape (for opacity <= 0.5 you have to click on the border of the shape), but you cannot start a new shape within an existing shape (which is possible for an opacity <= 0.5).
769+
770+
```python
771+
import plotly.graph_objects as go
772+
fig = go.Figure()
773+
text="Click and drag<br> to draw a rectangle <br><br> or select another shape <br>in the modebar"
774+
fig.add_annotation(
775+
x=0.5,
776+
y=0.5,
777+
text=text,
778+
xref="paper",
779+
yref="paper",
780+
showarrow=False,
781+
font_size=20
782+
)
783+
# shape defined programatically
784+
fig.add_shape(line_color='yellow',
785+
fillcolor='turquoise',
786+
opacity=0.4,
787+
editable=True,
788+
x0=0, x1=1, y0=2, y1=3,
789+
xref='x1', yref='y1'
790+
)
791+
fig.update_layout(dragmode='drawrect',
792+
# style of new shapes
793+
newshape=dict(line_color='yellow',
794+
fillcolor='turquoise',
795+
opacity=0.5))
796+
fig.show(config={'modeBarButtonsToAdd':['drawline',
797+
'drawopenpath',
798+
'drawclosedpath',
799+
'drawcircle',
800+
'drawrect',
801+
'eraseshape'
802+
]})
803+
```
804+
719805
### Reference
720806
See https://plotly.com/python/reference/#layout-shapes for more information and chart attribute options!

0 commit comments

Comments
 (0)