Skip to content

Commit 21df030

Browse files
docs and tests for imshow changes
1 parent 941779c commit 21df030

File tree

5 files changed

+101
-31
lines changed

5 files changed

+101
-31
lines changed

Diff for: doc/python/heatmaps.md

+18-4
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ jupyter:
3636

3737
### Heatmap with `plotly.express` and `px.imshow`
3838

39-
[Plotly Express](/python/plotly-express/) is the easy-to-use, high-level interface to Plotly. With `px.imshow`, each value of the input array is represented as a heatmap pixel.
40-
41-
`px.imshow` makes opiniated choices for representing heatmaps, such as using square pixels. To override this behaviour, you can use `fig.update_layout` or use the `go.Heatmap` trace from `plotly.graph_objects` as described below.
39+
[Plotly Express](/python/plotly-express/) is the easy-to-use, high-level interface to Plotly, which [operates on "tidy" data](/python/px-arguments/) and produces [easy-to-style figures](/python/styling-plotly-express/). With `px.imshow`, each value of the input array is represented as a heatmap pixel.
4240

4341
For more examples using `px.imshow`, see the [tutorial on displaying image data with plotly](/python/imshow).
4442

@@ -51,6 +49,22 @@ fig = px.imshow([[1, 20, 30],
5149
fig.show()
5250
```
5351

52+
### Customizing the axes and labels on a heatmap
53+
54+
You can use the `x`, `y` and `labels` arguments to customize the display of a heatmap, and use `.update_xaxes()` to move the x axis tick labels to the top:
55+
56+
```python
57+
import plotly.express as px
58+
data=[[1, 25, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, 5, 20]]
59+
fig = px.imshow(data,
60+
labels=dict(x="Day of Week", y="Time of Day", color="Productivity"),
61+
x=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
62+
y=['Morning', 'Afternoon', 'Evening']
63+
)
64+
fig.update_xaxes(side="top")
65+
fig.show()
66+
```
67+
5468
### Basic Heatmap with `plotly.graph_objects`
5569

5670
If Plotly Express does not provide a good starting point, it is also possible to use the more generic `go.Heatmap` function from `plotly.graph_objects`.
@@ -67,7 +81,7 @@ fig.show()
6781

6882
### Heatmap with Categorical Axis Labels
6983

70-
In this example we also show how to ignore [hovertext](https://plot.ly/python/hover-text-and-formatting/) when we have [missing values](https://plot.ly/python/missing_values) in the data by setting the [hoverongaps](https://plot.ly/python/reference/#heatmap-hoverongaps) to False.
84+
In this example we also show how to ignore [hovertext](https://plot.ly/python/hover-text-and-formatting/) when we have [missing values](https://plot.ly/python/missing_values) in the data by setting the [hoverongaps](https://plot.ly/python/reference/#heatmap-hoverongaps) to False.
7185

7286
```python
7387
import plotly.graph_objects as go

Diff for: doc/python/imshow.md

+36-13
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ fig = px.imshow(img)
7474
fig.show()
7575
```
7676

77-
### Display single-channel 2D image as grayscale
77+
### Display single-channel 2D data as a heatmap
7878

7979
For a 2D image, `px.imshow` uses a colorscale to map scalar data to colors. The default colorscale is the one of the active template (see [the tutorial on templates](/python/templates/)).
8080

@@ -88,44 +88,67 @@ fig.show()
8888

8989
### Choose the colorscale to display a single-channel image
9090

91+
You can customize the [continuous color scale](/python/colorscales/) just like with any other Plotly Express function:
9192

9293
```python
9394
import plotly.express as px
9495
import numpy as np
9596
img = np.arange(100).reshape((10, 10))
96-
fig = px.imshow(img, color_continuous_scale='gray', labels=dict(x="yoo", y="yaa", color="hey"),
97-
width=600, height=600,
98-
x=["a","b","c","d","e","f","g","h","i","j"],
99-
y=["a","b","c","d","e","f","g","h","i","j"]
100-
)
97+
fig = px.imshow(img, color_continuous_scale='Viridis')
98+
fig.show()
99+
```
100+
101+
You can use this to make the image grayscale as well:
102+
103+
```python
104+
import plotly.express as px
105+
import numpy as np
106+
img = np.arange(100).reshape((10, 10))
107+
fig = px.imshow(img, color_continuous_scale='gray')
101108
fig.show()
102109
```
103110

104-
### Hiding the colorbar when displaying a single-channel image
111+
### Hiding the colorbar and axis labels
105112

106-
See [the tutorial on coloraxis](/python/colorscales/#share-color-axis) for more details on coloraxis.
113+
See the [continuous color](/python/colorscales/) and [cartesian axes](/python/axes/) pages for more details.
107114

108115
```python
109116
import plotly.express as px
110117
from skimage import data
111118
img = data.camera()
112119
fig = px.imshow(img, color_continuous_scale='gray')
113120
fig.update_layout(coloraxis_showscale=False)
121+
fig.update_xaxes(showticklabels=False)
122+
fig.update_yaxes(showticklabels=False)
123+
fig.show()
124+
```
125+
126+
### Customizing the axes and labels on a single-channel image
127+
128+
You can use the `x`, `y` and `labels` arguments to customize the display of a heatmap, and use `.update_xaxes()` to move the x axis tick labels to the top:
129+
130+
```python
131+
import plotly.express as px
132+
data=[[1, 25, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, 5, 20]]
133+
fig = px.imshow(data,
134+
labels=dict(x="Day of Week", y="Time of Day", color="Productivity"),
135+
x=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
136+
y=['Morning', 'Afternoon', 'Evening']
137+
)
138+
fig.update_xaxes(side="top")
114139
fig.show()
115140
```
116141

117142
### Display an xarray image with px.imshow
118143

119-
[xarrays](http://xarray.pydata.org/en/stable/) are labeled arrays (with labeled axes and coordinates). If you pass an xarray image to `px.imshow`, its axes labels and coordinates will be used for axis titles. If you don't want this behavior, you can pass `img.values` which is a NumPy array if `img` is an xarray. Alternatively, you can override axis titles hover labels and colorbar title using the `labels` attribute, as in the next example.
144+
[xarrays](http://xarray.pydata.org/en/stable/) are labeled arrays (with labeled axes and coordinates). If you pass an xarray image to `px.imshow`, its axes labels and coordinates will be used for axis titles. If you don't want this behavior, you can pass `img.values` which is a NumPy array if `img` is an xarray. Alternatively, you can override axis titles hover labels and colorbar title using the `labels` attribute, as above.
120145

121146
```python
122147
import plotly.express as px
123148
import xarray as xr
124149
# Load xarray from dataset included in the xarray tutorial
125150
airtemps = xr.tutorial.open_dataset('air_temperature').air.sel(lon=250.0)
126-
fig = px.imshow(airtemps.T, color_continuous_scale='RdBu_r', origin='lower',
127-
labels={'color':airtemps.attrs['var_desc']}
128-
)
151+
fig = px.imshow(airtemps.T, color_continuous_scale='RdBu_r', origin='lower')
129152
fig.show()
130153
```
131154

@@ -233,7 +256,7 @@ fig.show()
233256
### imshow and datashader
234257

235258
Arrays of rasterized values build by datashader can be visualized using
236-
imshow. See the [plotly and datashader tutorial](/python/datashader/) for
259+
imshow. See the [plotly and datashader tutorial](/python/datashader/) for
237260
examples on how to use plotly and datashader.
238261

239262

Diff for: packages/python/plotly/plotly/express/_doc.py

+3-10
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@
66
except AttributeError: # python 2
77
getfullargspec = inspect.getargspec
88

9-
# TODO contents of columns
10-
# TODO explain categorical
11-
# TODO handle color
12-
# TODO handle details of box/violin/histogram
13-
# TODO handle details of column selection with `dimensions`
14-
# TODO document "or `None`, default `None`" in various places
15-
# TODO standardize positioning and casing of 'default'
169

1710
colref_type = "str or int or Series or array-like"
1811
colref_desc = "Either a name of a column in `data_frame`, or a pandas Series or array_like object."
@@ -325,11 +318,11 @@
325318
],
326319
title=["str", "The figure title."],
327320
template=[
328-
"or dict or plotly.graph_objects.layout.Template instance",
329-
"The figure template name or definition.",
321+
"str or dict or plotly.graph_objects.layout.Template instance",
322+
"The figure template name (must be a key in plotly.io.templates) or definition.",
330323
],
331324
width=["int (default `None`)", "The figure width in pixels."],
332-
height=["int (default `600`)", "The figure height in pixels."],
325+
height=["int (default `None`)", "The figure height in pixels."],
333326
labels=[
334327
"dict with str keys and str values (default `{}`)",
335328
"By default, column names are used in the figure for axis titles, legend entries and hovers.",

Diff for: packages/python/plotly/plotly/express/_imshow.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,24 @@ def imshow(
101101
a multichannel image of floats, the max of the image is computed and zmax is the
102102
smallest power of 256 (1, 255, 65535) greater than this max value,
103103
with a 5% tolerance. For a single-channel image, the max of the image is used.
104+
Overridden by range_color.
104105
105106
origin : str, 'upper' or 'lower' (default 'upper')
106107
position of the [0, 0] pixel of the image array, in the upper left or lower left
107108
corner. The convention 'upper' is typically used for matrices and images.
108109
109110
labels : dict with str keys and str values (default `{}`)
110-
Overrides names used in the figure for axis titles (keys ``x`` and ``y``),
111-
colorbar title and hover (key ``color``). The values should correspond
111+
Sets names used in the figure for axis titles (keys ``x`` and ``y``),
112+
colorbar title and hoverlabel (key ``color``). The values should correspond
112113
to the desired label to be displayed. If ``img`` is an xarray, dimension
113114
names are used for axis titles, and long name for the colorbar title
114115
(unless overridden in ``labels``). Possible keys are: x, y, and color.
115116
117+
x, y: list-like, optional
118+
x and y are used to label the axes of single-channel heatmap visualizations and
119+
their lengths must match the lengths of the second and first dimensions of the
120+
img argument. They are auto-populated if the input is an xarray.
121+
116122
color_continuous_scale : str or list of str
117123
colormap used to map scalar data to colors (for a 2D image). This parameter is
118124
not used for RGB or RGBA images. If a string is provided, it should be the name
@@ -121,7 +127,7 @@ def imshow(
121127
122128
color_continuous_midpoint : number
123129
If set, computes the bounds of the continuous color scale to have the desired
124-
midpoint.
130+
midpoint. Overridden by range_color or zmin and zmax.
125131
126132
range_color : list of two numbers
127133
If provided, overrides auto-scaling on the continuous color scale, including
@@ -138,7 +144,7 @@ def imshow(
138144
The figure width in pixels.
139145
140146
height: number
141-
The figure height in pixels, defaults to 600.
147+
The figure height in pixels.
142148
143149
aspect: 'equal', 'auto', or None
144150
- 'equal': Ensures an aspect ratio of 1 or pixels (square pixels)
@@ -207,6 +213,16 @@ def imshow(
207213

208214
# For 2d data, use Heatmap trace
209215
if img.ndim == 2:
216+
if y is not None and img.shape[0] != len(y):
217+
raise ValueError(
218+
"The length of the y vector must match the length of the first "
219+
+ "dimension of the img matrix."
220+
)
221+
if x is not None and img.shape[1] != len(x):
222+
raise ValueError(
223+
"The length of the x vector must match the length of the second "
224+
+ "dimension of the img matrix."
225+
)
210226
trace = go.Heatmap(x=x, y=y, z=img, coloraxis="coloraxis1")
211227
autorange = True if origin == "lower" else "reversed"
212228
layout = dict(yaxis=dict(autorange=autorange))

Diff for: packages/python/plotly/plotly/tests/test_core/test_px/test_imshow.py

+24
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,27 @@ def test_imshow_xarray():
126126
assert fig.layout.xaxis.title.text == "dim_cols"
127127
assert fig.layout.yaxis.title.text == "dim_rows"
128128
assert np.all(np.array(fig.data[0].x) == np.array(da.coords["dim_cols"]))
129+
130+
131+
def test_imshow_labels_and_ranges():
132+
fig = px.imshow([[1, 2], [3, 4], [5, 6]],)
133+
assert fig.layout.xaxis.title.text is None
134+
assert fig.layout.yaxis.title.text is None
135+
assert fig.layout.coloraxis.colorbar.title.text is None
136+
assert fig.data[0].x is None
137+
assert fig.data[0].y is None
138+
fig = px.imshow(
139+
[[1, 2], [3, 4], [5, 6]],
140+
x=["a", "b"],
141+
y=["c", "d", "e"],
142+
labels=dict(x="the x", y="the y", color="the color"),
143+
)
144+
# Dimensions are used for axis labels and coordinates
145+
assert fig.layout.xaxis.title.text == "the x"
146+
assert fig.layout.yaxis.title.text == "the y"
147+
assert fig.layout.coloraxis.colorbar.title.text == "the color"
148+
assert fig.data[0].x[0] == "a"
149+
assert fig.data[0].y[0] == "c"
150+
151+
with pytest.raises(ValueError):
152+
fig = px.imshow([[1, 2], [3, 4], [5, 6]], x=["a"])

0 commit comments

Comments
 (0)